Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
[原文发表地址] Learn C++ Concepts with Visual Studio and the WSL
[原文作者] Andrew Pardoe
[原文发表时间] 2017/2/22
Concepts是可以从概念上改变C++模板代码的使用. 与Coroutines,Modules,ranges特性一样,Concepts位于技术指标(TS)中, 在它们将要列入C++标准前去学习并使用这些重要的特性,是很有帮助的. 你已经可以使用VS 2017中已增加的Coroutines,Modules以及Range-V3分支中的Ranges特性. 现在我们又在VS2017针对Windows中的linux子系统模块(WSL)中支持使用Concept. 我们来看看他们是如何工作的.
关于Concepts
模板参数可以通过Concept来确定它所必须的条件, 这也是创建不同接口的本质条件. C++社区期盼很多年希望Concepts加入C++标准。 如果你对于这些事感兴趣, 可以阅读Bjarne Stroustrup写的一些关于concept背景需求的一些文章。 a recent paper about designing good concepts.如果你对于如果使用concept感兴趣, 请参考 Constraints and concepts on cppreference.com. 如果想知道关于concepts的所有细节, 你可以阅读 Concepts Technical Specification (TS).
Concepts当前仅在Gcc 6版本以上可用。 它还没有被MSVC和Clang编译器所支持。 我们计划先完成当前已经被投票通过的C++17特性, 并完成一些还没有实现的准则,然后我们就会在MSVC的TS里实现Concept.
我们可以通过VS2017包含的linux for windows子系统指定Linux shell为目标, 这样我们就可以在VS中使用concepts. 因为没有IDE界面的支持,也没有智能感应等来提高编码效率. 但是在我们熟悉的shell命令符窗体下也可以很好的学习Concepts, 毕竟我们每天都在使用command命令行窗口.
因为当前包含在WSL中的GCC版本是4.84.这个版本还不支持concepts. 我们需要先更新GCC编译器。 有两种方法,一种是安装Personal package archive(PPA)或者直接通过源码生成 GCC-6.
在安装GCC-6前, 你需要在VS2017上安装配置WSL, 参考Targeting the Windows Subsystem for Linux from Visual Studio.这篇博客. 配置好VS,并将工程目标指定到Linux. 这需要下面这些步骤,熟悉每一步将会帮助你更快的解决遇到的问题。
安装GCC-6
有两种方式可供选择, 从PPA上安装,直接通过源码生成并安装.
使用PPA安装GCC
PPA允许通过apt安装,PPA可以帮助你需要的软件. 通过安装Toolchain Test PPA ,更新apt得到最新版本的GCC. 然后安装g++-6.
PPA安装GCC,并不会把GCC设为默认编译器。 运行g++ --version会显示4.8.4版本.你可以通过使用g++-6来调用最新版本的gcc.如果gcc6不是默认编译器,你需要在你的Linux项目中将VS的远程编译器设置为GCC6.
从源码生成GCC
直接通过源代码生成GCC 6.3可以通过下面这几个过程.
1. 获得GCC 6.3的源码. 在下载前,需要指定源代码的URL档案, 从最近镜像mirror找到并拷贝档案URL,我将使用tar.gz作为例子。
wget https://[path to archive]/gcc-6.3.0.tar.gz
2. 使用命令解压GCC的源代码(将/mnt/c/tmp to the改为gcc-6.3.0.tar.gz的位置.
tar -xvf /mnt/c/tmp/gcc-6.3.0.tar.gz
3. 获得了GCC源代码后, 安装GCC必须的库. 参考 Installing GCC, Support libraries 以获得更多的信息. GCC需要3个前置库, 我们可以通过apt来安装它们:
sudo apt install libgmp-dev
sudo apt install libmpfr-dev
sudo apt install libmpc-dev
4. 现在我们可以生成一个目标目录,并配置GCC的生成过程, 最终得到我们需要的C++编译器.
cd gcc-6.3.0/
mkdir build
cd build
../configure --enable-languages=c,c++ --disable-multilib
5. 配置完成后, 我们可以编译GCC. 编译生成的过程需要花费一些时间, 当然我们可以使用 -J选项加快生成速度。
make –j
6. 如果生成成功没有错误, 就可以在Linux下安装GCC了, 下面这条命令将会安装GCC 6.3.0并作为默认的GCC版本.
sudo make install
You can check that GCC is now defaulting to version 6.3 with this command:
$ gcc --version
gcc (GCC) 6.3.0
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
尝试在VS上使用C++ Concepts
现在可以尝试使用GCC的Concepts了! 让我们重新启动SSH服务(以防意外退出bash命令行).
sudo service ssh start
在VS上创建新的Linux项目:
添加C++源文件, 并添加使用Concepts的C++代码.下面是一个简单的Demo。这个例子很常见, 编译器对于没有定义operator==重载操作的参数i会提示错误,当然我们根据错误可以知道这里运用了concepts.
#include <iostream>
template<``classT>
concept ``boolEqualityComparable() {
``returnrequires(T a, T b) {
``{a == b}->``bool``;
``{a != b}->``bool``;
``};
}
boolis_the_answer(``constEqualityComparable& i) {
``return (i == 42) ? ``true : ``false``;
}
intmain() {
``if(is_the_answer(42)) {
`` std::cout << ``"42 is the answer to the ultimate question of life, the universe, and everything."<< std::endl;
``}
``return0;
}
你还需要在GCC命令行开启concept. 在项目属性中的C++->Command Line对话框中加入编译选项 –fconcepts
如果你默认环境里告诉VS如何去找的编译器的地方设置的不是GCC6,你可以在项目属性页面设置:C++ > 通用 >C++编译器输入编译器的名字或者甚至是完整路径
在main函数的结尾添加断点,编译程序.打开Linux 中断你会看到输出.(Debug>Linux) F5并观察concepts在VS里是如果工作的
这样你就可以在VS IDE里面使用Concepts,Coroutines,Modules,以及Ranges特性.
举例 :concepts分派
上面的例子虽然给出了concepts的一些特性, 但是并没有做什么事情.下面是来自Casey Carter的一个目的性明确的例子, 这里使用了type trait来展示concepts的分派. 这个例子阐述了concepts分派过程中应该注意哪些约束性.
#include <iostream>
#include <type_traits>
template``<``classT>
concept ``boolIntegral = std::is_integral<T>::value;
template``<``classT>
concept ``boolSignedIntegral = Integral<T> && T(-1) < T(0);
template``<``classT>
concept ``boolUnsignedIntegral = Integral<T> && T(0) < T(-1);
template``<``classT>
void f(T ``const``& t) {
`` std::cout << ``"Not integral: " << t << ``'\n'``;
}
void f(Integral) = ``delete``;
voidf(SignedIntegral i) {
`` std::cout << ``"SignedIntegral: " << i << ``'\n'``;
}
voidf(UnsignedIntegral i) {
`` std::cout << ``"UnsignedIntegral: " << i << ``'\n'``;
}
intmain() {
``f(42);
``f(1729u);
``f(``"Hello, World!"``);
``enum{ bar };
``f(bar);
``f(``'a'``);
``f(L``'a'``);
``f(U``'a'``);
``f(``true``);
}
结语
和往常一样, 我们欢迎你的反馈, 反馈方式可以是 visualcpp@microsoft.com Twitter @visualc, 或者 Microsoft Visual Cpp的脸书.
如果在使用VS 2017的VC++ 过程中遇到任何问题, 请通过 Report a Problem 选项, 或者VS IDE安装工具告诉我们. 使用UserVoice发送您的建议. 谢谢!