如何在cmake项目中制作某些所需的c ++功能?

时间:2018-07-22 09:08:06

标签: c++ c++11 cmake c++14

我正在为我的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)
...

1 个答案:

答案 0 :(得分:0)

因为我认为这是一个常见问题,所以我自己回答:

虽然一般用法是正确的,但是如果要编写库,则需要调整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一起引入的。除了现有的十六进制文字外,它们还允许以二进制形式写入值。

二进制文字用二进制值前面的0b0B标记:

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中与N2928N3206N3272一起引入的。它使类设计者可以防止用户覆盖虚拟函数或成员函数。

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,则它们可确保在调用它们时不会引发任何异常。此外,可以通过noexcept(f)函数测试“ noexception”。

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