1. CMake在某一个target中清空include_directory

我们都知道,现代CMake是面向target的。在设置target的头文件搜索路径时,也推荐使用target_include_directory单独为某个target设置头文件搜索路径,并同时设置路径对其他目标的可见性(private, interface…)。

但如果你在参与一个有一定历史的大型项目,其CMake可能经历了好“几代”程序员的维护,就有可能出现target_include_directoryinclude_directory混用的情况。如果恰巧两个目标里面,又有同名的头文件,就会出现诡异的事情了 :(

有没有办法解决这种问题呢?

有,使用CMake的set_property

例:

set_property(
    TARGET
    target_name
    PROPERTY
    INCLUDE_DIRECTORIES ""
)

可以看到,通过set_propertyINCLUDE_DIRECTORIES属性设置为空就ok啦

需要注意的是set_property的顺序,不要将想要添加的路径也清空呀

2. C++大括号初始化与初始化列表及窄化类型转换

首先来看一段示例代码:

auto count_unique(const std::array<int32_t, 3>& v)
{
    return std::unordered_set<bool>{v.begin(), v.end()}.size();
}

auto ret = count_unique({0, 1, 2})

Q:请问这段代码得到的set中,有哪些元素呢?
符合直觉地,我们可能会回答:
2个元素: true, false.因为0类型转换为了false2转换为了true

但答案却是:
1个元素.
因为如果有初始化列表为参数的构造函数,大括号初始化就会优先匹配初始化列表为参数的构造函数.
不幸的是,在这段代码中,编译器认为unordered_set的这个这个大括号初始化应该匹配初始化列表为参数的构造函数.
而在libc++ 及 libstdc++的实现中,v.begin() v.end() 为指针.因此,编译器将这两个指针强转为了bool.即,我们其实使用了两个bool值来初始化这个容器.

如何解决这个问题?
我们可以将指针到bool的类型转换定义为"窄化"的.
那为什么"窄化"的类型转换就可以避免这个问题了呢?
因为在初始化列表的参数,是不接受"窄化"的类型转换的,即如果指针到bool的类型转换定义为"窄化"的,我们的这段代码将会通不过编译.

From: https://isocpp.org/files/papers/P1957R2.html