因为我觉得这是一个常见的问题,所以我会自己回答:
虽然一般用法是正确的,但如果您正在编写库,则需要调整 cmake 代码:
target_compile_features(myproject INTERFACE cxx_auto_type)
此外,您需要根据您使用的内容添加更多功能。这可以通过简单地列出它们来完成:
target_compile_features(myproject INTERFACE cxx_auto_type
cxx_static_assert
...)
CMAKE_CXX_KNOWN_FEATURES
可以在 cmake documentation 中找到可能值的列表。但是,我发现 c++ 标准的简短句子和链接并没有真正的帮助。因此,我将尝试描述每个选项所包含的功能。
我想解释列表中的所有选项,但是要花一些时间来写...因此,我将从我认为有用或有趣的功能开始,但稍后会尝试添加更多功能。如果有人想添加我尚未发布的内容,我也将不胜感激。
我将链接与原版相同的 c++ 标准文档,但如果需要,我还将提供指向相应 cppreference 页面的链接和一个小的编码示例。
cxx_auto_type
Auto type deduction 是在 c++11 中以N1984 引入的。它允许用户在所有情况下编写auto 关键字,编译器可以自动推断结果类型。不必再给出实际类型。
例如:
auto i = 0; //it is clear that we want an int here
auto d = 1.45; //it is clear that we want a double here
...
cxx_binary_literals
Binary literals 是在 c++14 中以N3472 引入的。除了现有的十六进制文字外,它们还允许以二进制形式写入值。
二进制字面量在二进制值前面用0b 或0B 标记:
0B1000 == 8 //true
0b1001 == 9 //true
cxx_deleted_functions
Deleted functions 在 c++11 中以N2346 引入。它们允许用户显式删除类中的某些运算符和成员函数。如果程序将访问任何已删除的函数,则代码将无法编译:
struct no_default_constructor {
no_default_constructor() = delete; //the default constructor is deleted
no_default_constructor(int value) : ...
...
};
因此,默认构造是不可能的,但可能是另一种构造。
no_default_constructor object = no_default_constructor(); //this will not compile
no_default_constructor object = no_default_constructor(2); //this will
cxx_explicit_conversions
Explicit conversions 在 c++11 中添加了 N2437。它们允许将类转换指定为显式,这意味着不可能进行隐式转换。
例如:
struct flag {
bool is_set;
explicit operator bool() const { return is_set; }
};
这个类不能隐式转换为bool,但是显式转换还是可以的:
void print_birthday_message(flag user_has_birthday) {
bool has_birthday = user_has_birthday; //this is not possible
bool has_birthday = bool(user_has_birthday); //but this is fine
...
}
cxx_final
final keyword 是在 c++11 中引入的,带有 N2928、N3206 和 N3272。它允许类设计者防止用户覆盖虚函数或成员函数。
final 关键字必须写在虚函数的末尾,以防止额外的覆盖:
struct Base {
virtual void function();
};
struct A : Base {
void function() final; //overwrite Base::function and make it the final overwrite
};
struct B : A {
void function() override; //this is not possible, as function was already marked final inside A
};
final 关键字必须位于派生类名称的末尾,以防止被覆盖:
struct Base {};
struct A final : Base {}; //struct A is now final
struct B : A {}; //this is not possible, as A was already marked final
cxx_noexcept
noexcept keyword 是在 c++11 中与N3050 一起引入的。它允许标记函数、运算符和构造函数。如果这些标记为noexcept,则它们保证在调用它们时不会引发异常。此外,“noexceptness”可以通过noexcept(f) 函数进行测试。
cxx_raw_string_literals
Raw string literals 是在 c++11 中与N2442 一起引入的。它们允许在不使用转义字符的情况下将任意字符写入字符串。
原始字符串采用R"delimiter(raw_characters)delimiter" 的形式,delimiter 是任意名称(遵循 c++ 命名标准)。一个常见的情况是使用它们直接在 c++ 中输入脚本代码。另外,delimiter 会被编译器忽略,使用它为 IDE 提供脚本语言提示。
例如:
const char* code = R"chaiscript(
print("Hello World")
)chaiscript";
cxx_strong_enums
Strongly typed enums 在 c++11 中以N2347 引入。它们允许以某种方式设置枚举的类型,从而防止枚举的错误被自动转换为其他类型。
强类型枚举使用enum class name 语法。例如:
enum class colours {
cyan = 0,
red = 1,
green = 2,
};
这使得意外转换不可能:
int color_index = colours::green; //this conversion is not allowed!
int color_index = int(colours::green); //explicit casts are still okay
cxx_trailing_return_types
Trailing return types 是在 c++11 中以N2541 引入的。它们允许在参数列表之后定义函数的返回类型:
auto greet() -> void {
std::cout << "Hello World!";
}
尾随返回类型在 AAA(几乎总是自动)编程风格中很有用,并且在返回类型很复杂的情况下,或者在模板函数中它可能取决于输入类型。
cxx_unicode_literals
Unicode literals 是在 c++11 中以N2442 引入的。它们允许用户直接将 unicode 字符输入到 c++ 中,而无需使用 unicode 转义字符。 (\n, ... 还是要转义。)
它们采用u8"(characters)" 的形式。 u8 是否可以替换以更改底层数据类型:
const char* utf8 = u8"(characters)";
const char16_t* utf16 = u"(characters)";
const char32_t* utf32 = U"(characters)";
cxx_user_literals
User literals 是在 c++11 中以N2765 引入的。它们允许用户编写自定义类型快捷方式和自定义类型转换。
用户文字使用operator "" 定义。例如,从度数到弧度的转换可以写成:
constexpr double operator "" _degrees(double value) {
return value*3.14/180.;
}
该值通过以下方式获得:
double theta = 90_degrees; //==1.57