{"id":12685,"date":"2017-02-22T15:08:30","date_gmt":"2017-02-22T22:08:30","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/vcblog\/?p=12685"},"modified":"2019-02-18T17:48:42","modified_gmt":"2019-02-18T17:48:42","slug":"learn-c-concepts-with-visual-studio-and-the-wsl","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cppblog\/learn-c-concepts-with-visual-studio-and-the-wsl\/","title":{"rendered":"Learn C++ Concepts with Visual Studio and the WSL"},"content":{"rendered":"<p><a href=\"https:\/\/blogs.msdn.microsoft.com\/c\/2017\/03\/29\/%E4%BD%BF%E7%94%A8visual-studio%E4%B8%8B%E7%9A%84linux%E5%AD%90%E7%B3%BB%E7%BB%9F%E6%9D%A5%E5%AD%A6%E4%B9%A0c-concepts\/\">\u70b9\u8fd9\u91cc\u770b\u4e2d\u6587\u7248<\/a><\/p>\n<p>Concepts promise to fundamentally change how we write templated C++ code. They&#8217;re in a Technical Specification (TS) right now, but, like Coroutines, Modules, and Ranges, it&#8217;s good to get a head start on learning these important features before they make it into the C++ Standard. You can already use Visual Studio 2017 for Coroutines, Modules, and Ranges through a fork of <a href=\"https:\/\/github.com\/microsoft\/Range-V3-VS2015\">Range-v3<\/a>. Now you can also learn Concepts in Visual Studio 2017 by targeting the Windows Subsystem for Linux (WSL). Read on to find out how!<\/p>\n<h4>About concepts<\/h4>\n<p>Concepts enable adding requirements to a set of template parameters, essentially creating a kind of interface. The C++ community has been waiting years for this feature to make it into the standard. If you&#8217;re interested in the history, Bjarne Stroustrup has written a bit of background about concepts in <a href=\"http:\/\/open-std.org\/JTC1\/SC22\/WG21\/docs\/papers\/2017\/p0557r0.pdf\">a recent paper about designing good concepts<\/a>. If you&#8217;re just interested in knowing how to use the feature, see <a href=\"http:\/\/en.cppreference.com\/w\/cpp\/language\/constraints\">Constraints and concepts on cppreference.com<\/a>. If you want all the details about concepts you can read the <a href=\"http:\/\/www.open-std.org\/jtc1\/sc22\/wg21\/docs\/papers\/2015\/n4549.pdf\">Concepts Technical Specification (TS)<\/a>.<\/p>\n<p>Concepts are currently only available in GCC 6+. Concepts are not yet supported by the Microsoft C++ Compiler (MSVC) or Clang. We plan to implement the Concepts TS in MSVC but our focus is on finishing our existing standards conformance work and implementing features that have already been voted into the C++17 draft standard. <\/p>\n<p>We can use concepts in Visual Studio 2017 by targeting the Linux shell running under WSL. There&#8217;s no IDE support for concepts&#8211;thus, no IntelliSense or other productivity features that require the compiler&#8211;but it&#8217;s nice to be able to learn Concepts in the same familiar environment you use day to day. <\/p>\n<p>First we have to update the GCC compiler. The version included in WSL is currently 4.8.4&#8211;that&#8217;s too old to support concepts. There are two ways to accomplish that: installing a Personal Package Archive (PPA) or building GCC-6 from source. <\/p>\n<p>But before you install GCC-6 you should configure your Visual Studio 2017 install to target WSL. See this recent VCBlog post for details: <a href=\"https:\/\/blogs.msdn.microsoft.com\/vcblog\/2017\/02\/08\/targeting-windows-subsystem-for-linux-from-visual-st\">Targeting the Windows Subsystem for Linux from Visual Studio<\/a>. You&#8217;ll need a working setup of VS targeting Linux for the following steps. Plus, it&#8217;s always good to conquer problems in smaller pieces so you have an easier time figuring out what happened if things go wrong.<\/p>\n<h4>Installing GCC-6<\/h4>\n<p>You have two options for installing GCC-6: installing from a PPA or building GCC from source. <\/p>\n<h5>Using a PPA to install GCC<\/h5>\n<p>A PPA allows developers to distribute programs directly to users of apt. Installing a PPA tells your copy of apt that there&#8217;s another place it can find software. To get the newest version of GCC, install the <a href=\"https:\/\/launchpad.net\/~ubuntu-toolchain-r\/+archive\/ubuntu\/test\">Toolchain Test PPA<\/a>, update your apt to find the new install locations, then install g++-6.<\/p>\n<pre class=\"prettyprint disable-colors\">\nsudo add-apt-repository ppa:ubuntu-toolchain-r\/test\nsudo apt update\nsudo apt install g++-6\n<\/pre>\n<p>The PPA installs GCC as a non-default compiler. Running <code>g++ --version<\/code> shows version 4.8.4. You can invoke GCC by calling <code>g++-6<\/code> instead of <code>g++<\/code>. If GCC 6 isn&#8217;t your default compiler you&#8217;ll need to change the remote compiler that VS calls in your Linux project (see below.)<\/p>\n<pre class=\"prettyprint disable-colors\">\ng++ --version\ng++-6 --version\n<\/pre>\n<h5>Building GCC from source<\/h5>\n<p>Another option is to build GCC 6.3 from source. There are a few steps, but it&#8217;s a straightforward process. <\/p>\n<ol>\n<li>First you need to get a copy of the <a href=\"https:\/\/gcc.gnu.org\/gcc-6\/\">GCC 6.3 sources<\/a>. Before you can download this to your bash shell, you need to get a link to the source archive. Find a nearby <a href=\"https:\/\/gcc.gnu.org\/mirrors.html\">mirror<\/a> and copy the archive&#8217;s URL. I&#8217;ll use the <code>tar.gz<\/code> in this example:\n<pre class=\"prettyprint disable-colors\">\nwget http:\/\/[path to archive]\/gcc-6.3.0.tar.gz\n<\/pre>\n<\/li>\n<li>\nThe command to unpack the GCC sources is as follows (change <code>\/mnt\/c\/tmp<\/code> to the directory where your copy of gcc-6.3.0.tar.gz is located):<\/p>\n<pre class=\"prettyprint disable-colors\">\ntar -xvf \/mnt\/c\/tmp\/gcc-6.3.0.tar.gz\n<\/pre>\n<\/li>\n<li>\nNow that we&#8217;ve got the GCC sources, we need to install the GCC prerequisites. These are libraries required to build GCC. (See <a href=\"https:\/\/gcc.gnu.org\/wiki\/InstallingGCC\">Installing GCC, Support libraries<\/a> for more information.) There are three libraries, and we can install them with apt:<\/p>\n<pre class=\"prettyprint disable-colors\">\nsudo apt install libgmp-dev\nsudo apt install libmpfr-dev\nsudo apt install libmpc-dev\n<\/pre>\n<\/li>\n<li>\nNow let&#8217;s make a build directory and configure GCC&#8217;s build to provide C++ compilers:<\/p>\n<pre class=\"prettyprint disable-colors\">\ncd gcc-6.3.0\/\nmkdir build\ncd build\n..\/configure --enable-languages=c,c++ --disable-multilib\n<\/pre>\n<\/li>\n<li>\nOnce that finishes, we can compile GCC. It can take a while to build GCC, so you should use the <code>-j<\/code> option to speed things up. <\/p>\n<pre class=\"prettyprint disable-colors\">\nmake -j\n<\/pre>\n<p>Now go have a nice cup of coffee (and maybe watch a movie) while the compiler compiles. \n<\/li>\n<li>If <code>make<\/code> completes without errors, you&#8217;re ready to install GCC on your system. Note that this command installs GCC 6.3.0 as the default version of GCC. \n<pre class=\"prettyprint disable-colors\">\nsudo make install\n<\/pre>\n<p>You can check that GCC is now defaulting to version 6.3 with this command:<\/p>\n<pre class=\"prettyprint disable-colors\">\n$ gcc --version\ngcc (GCC) 6.3.0\nCopyright (C) 2016 Free Software Foundation, Inc.\nThis is free software; see the source for copying conditions.  There is NO\nwarranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n<\/pre>\n<\/li>\n<\/ol>\n<h4>Trying out Concepts in VS<\/h4>\n<p>Now that you&#8217;ve updated GCC you&#8217;re ready to try out concepts! Let&#8217;s restart the SSH service again (in case you exited all your bash instances while working through this walkthrough) and we&#8217;re ready to learn concepts!<\/p>\n<pre class=\"prettyprint disable-colors\">\nsudo service ssh start\n<\/pre>\n<p>Create a new Linux project in VS:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/NewLinuxProject.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/NewLinuxProject-300x207.png\" alt=\"newlinuxproject\" width=\"300\" height=\"207\" class=\"alignnone size-medium wp-image-12695\" \/><\/a><\/p>\n<p>Add a C++ source file, and add some code that uses concepts. Here&#8217;s a simple concept that compiles and executes properly. This example is trivial, as the compile would fail for any argument <code>i<\/code> that doesn&#8217;t define <code>operator==<\/code>, but it demonstrates that concepts are working. <\/p>\n<pre class=\"prettyprint\">\n#include &lt;iostream&gt;\n\ntemplate &lt;class T&gt;\nconcept bool EqualityComparable() {\n\treturn requires(T a, T b) {\n\t\t{a == b}-&gt;bool;\n\t\t{a != b}-&gt;bool;\n\t};\n}\n\nbool is_the_answer(const EqualityComparable&amp; i) {\n\treturn (i == 42) ? true : false;\n}\n\nint main() {\n\tif (is_the_answer(42)) {\n\t\tstd::cout &lt;&lt; &quot;42 is the answer to the ultimate question of life, the universe, and everything.&quot; &lt;&lt; std::endl;\n\t}\n\treturn 0;\n}\n<\/pre>\n<p>You&#8217;ll also need to enable concepts on the GCC command line. Go to the project properties, and in the C++ &gt; Command Line box add the compiler option <code>-fconcepts<\/code>.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/fconcepts.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/fconcepts-300x215.png\" alt=\"fconcepts\" width=\"300\" height=\"215\" class=\"alignnone size-medium wp-image-12725\" \/><\/a><\/p>\n<p>If GCC 6 isn&#8217;t the default compiler in your environment you&#8217;ll want to tell VS where to find your compiler. You can do that in the project properties under C++ &gt; General &gt; C++ compiler by typing in the compiler name or even a full path:<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/gplusplus6.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/gplusplus6-300x215.png\" alt=\"gplusplus6\" width=\"300\" height=\"215\" class=\"alignnone size-medium wp-image-12735\" \/><\/a><\/p>\n<p>Now compile the program and set a breakpoint at the end of <code>main<\/code>. Open the Linux Console so you can see the output (Debug &gt; Linux Console). Hit F5 and watch concepts working inside of VS!<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/Concepts.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/9\/2019\/02\/Concepts-300x210.png\" alt=\"concepts\" width=\"300\" height=\"210\" class=\"alignnone size-medium wp-image-12715\" \/><\/a><\/p>\n<p>Now we can use Concepts, Coroutines, Modules, and Ranges all from inside the same Visual Studio IDE!<\/p>\n<h4>Example: concept dispatch<\/h4>\n<p>The example above shows that concepts compile properly but it doesn&#8217;t really do anything. Here&#8217;s a more motivating example from Casey Carter that uses a type trait to show concept dispatch. This is a really great example to work through to illustrate the mechanics of constraints. <\/p>\n<pre class=\"prettyprint\">\n#include &lt;iostream&gt;\n#include &lt;type_traits&gt;\n\ntemplate&lt;class T&gt;\nconcept bool Integral = std::is_integral&lt;T&gt;::value;\n\ntemplate&lt;class T&gt;\nconcept bool SignedIntegral = Integral&lt;T&gt; &amp;&amp; T(-1) &lt; T(0);\n\ntemplate&lt;class T&gt;\nconcept bool UnsignedIntegral = Integral&lt;T&gt; &amp;&amp; T(0) &lt; T(-1);\n\ntemplate&lt;class T&gt;\nvoid f(T const&amp; t) {\n    std::cout &lt;&lt; &quot;Not integral: &quot; &lt;&lt; t &lt;&lt; '\\n';\n}\n\nvoid f(Integral) = delete;\n\nvoid f(SignedIntegral i) {\n    std::cout &lt;&lt; &quot;SignedIntegral: &quot; &lt;&lt; i &lt;&lt; '\\n';\n}\n\nvoid f(UnsignedIntegral i) {\n    std::cout &lt;&lt; &quot;UnsignedIntegral: &quot; &lt;&lt; i &lt;&lt; '\\n';\n}\n\nint main() {\n    f(42);\n    f(1729u);\n    f(&quot;Hello, World!&quot;);\n    enum { bar };\n    f(bar);\n    f('a');\n    f(L'a');\n    f(U'a');\n    f(true);\n}\n<\/pre>\n<h4>In closing<\/h4>\n<p>As always, we welcome your feedback. Feel free to send any comments through e-mail at <a>visualcpp@microsoft.com<\/a>, through <a href=\"https:\/\/twitter.com\/visualc\">Twitter @visualc<\/a>, or Facebook at <a href=\"https:\/\/www.facebook.com\/Microsoft-Visual-Cpp-222043184527264\/\">Microsoft Visual Cpp<\/a>. <\/p>\n<p>If you encounter other problems with Visual C++ in VS 2017 please let us know via the <a href=\"https:\/\/docs.microsoft.com\/en-us\/visualstudio\/ide\/how-to-report-a-problem-with-visual-studio-2017\">Report a Problem<\/a> option, either from the installer or the Visual Studio IDE itself. For suggestions, let us know through <a href=\"https:\/\/visualstudio.uservoice.com\/forums\/121579-visual-studio-2015\/category\/30937-languages-c\">UserVoice<\/a>. Thank you!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u70b9\u8fd9\u91cc\u770b\u4e2d\u6587\u7248 Concepts promise to fundamentally change how we write templated C++ code. They&#8217;re in a Technical Specification (TS) right now, but, like Coroutines, Modules, and Ranges, it&#8217;s good to get a head start on learning these important features before they make it into the C++ Standard. You can already use Visual Studio 2017 for Coroutines, [&hellip;]<\/p>\n","protected":false},"author":312,"featured_media":35994,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[279],"tags":[],"class_list":["post-12685","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-linux"],"acf":[],"blog_post_summary":"<p>\u70b9\u8fd9\u91cc\u770b\u4e2d\u6587\u7248 Concepts promise to fundamentally change how we write templated C++ code. They&#8217;re in a Technical Specification (TS) right now, but, like Coroutines, Modules, and Ranges, it&#8217;s good to get a head start on learning these important features before they make it into the C++ Standard. You can already use Visual Studio 2017 for Coroutines, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/12685","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/users\/312"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/comments?post=12685"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/posts\/12685\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media\/35994"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/media?parent=12685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/categories?post=12685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cppblog\/wp-json\/wp\/v2\/tags?post=12685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}