我正在为我的c ++ 14项目编写CMakeLists.txt
。我希望其他用户能够构建我的项目,但是他们的编译器可能不支持我正在使用的c ++ 14功能。如果编译器不支持我的c ++ 14代码,如何获取cmake打印错误消息?
我发现target_compile_features
command似乎做得不错。但是,我不确定如何正确使用它...
这对吗?
CMakeLists.txt:
project(myproject VERSION 1.0.0
LANGUAGES CXX)
add_executable(myproject src/main.cpp)
target_compile_features(myproject PRIVATE cxx_auto_type)
...
答案 0 :(得分:0)
因为我认为这是一个常见问题,所以我自己回答:
虽然一般用法是正确的,但是如果要编写库,则需要调整cmake代码:
target_compile_features(myproject INTERFACE cxx_auto_type)
此外,您需要根据使用的内容添加更多功能。只需列出所有内容即可完成:
target_compile_features(myproject INTERFACE cxx_auto_type
cxx_static_assert
...)
可以在cmake documentation中找到可能值的列表。但是,我发现简短的句子和指向c ++标准的链接并没有真正的帮助。因此,我将尝试描述每个选项包含的功能。
我想解释一下列表中的所有选项,但是要花很多时间写……因此,我将以我认为有用或有趣的功能开始,但以后会尝试添加更多功能。如果有人想添加我还没来发布的内容,我也将很感激。
我将链接与原始文档相同的c ++标准文档,但是如果需要,我还将提供指向相应的cppreference页面的链接和一个小的编码示例。
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
...
Binary literals是在c ++ 14中与N3472一起引入的。除了现有的十六进制文字外,它们还允许以二进制形式写入值。
二进制文字用二进制值前面的0b
或0B
标记:
0B1000 == 8 //true
0b1001 == 9 //true
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
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
...
}
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
noexcept keyword是在c ++ 11中与N3050一起引入的。它允许标记函数,运算符和构造函数。如果将这些标记为noexcept
,则它们可确保在调用它们时不会引发任何异常。此外,可以通过noexcept(f)
函数测试“ noexception”。
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";
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
Trailing return types是在c ++ 11中与N2541一起引入的。它们允许在参数列表后定义函数的返回类型:
auto greet() -> void {
std::cout << "Hello World!";
}
跟踪返回类型在AAA(几乎总是自动)编程样式中很有用,并且在返回类型很复杂的情况下,或者在模板函数中,返回类型可能取决于输入类型。
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)";
User literals是在c ++ 11中与N2765一起引入的。它们允许用户编写自定义类型快捷方式和自定义类型转换。
用户文字用operator ""
定义。例如,从度到弧度的转换可以这样写:
constexpr double operator "" _degrees(double value) {
return value*3.14/180.;
}
该值是通过以下方式获得的:
double theta = 90_degrees; //==1.57