1

跟进为什么 cppreference 将 type_traits xxx_v 快捷方式定义为内联 constexpr 而不仅仅是 constexpr?,如果我创建自己的类型特征并希望避免 ODR 违规并希望它与 C++17 之前的项目兼容,是否将 xxx_v 快捷方式放在匿名命名空间中与显式声明它内联相同?

例如,all_trueCheck traits for all variadic template arguments中获取,使用 C++17,我可以在我的实用程序头中编写:

template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
template <bool... v>
inline constexpr bool all_true_v = all_true<v...>::value;

这与编写以下与 pre-C++17 兼容的代码相同吗?

template <bool...> struct bool_pack;
template <bool... v>
using all_true = std::is_same<bool_pack<true, v...>, bool_pack<v..., true>>;
namespace {
   template <bool... v>
   constexpr bool all_true_v = all_true<v...>::value;
}
4

2 回答 2

3

考虑

    bool const* g_b= &all_true_v<true>;

这将在版本的每个翻译单元中具有相同的地址inline constexpr,但版本的地址不同namespace {}

于 2018-01-03T13:23:59.237 回答
2

您确实可以避免使用匿名命名空间的 ODR 违规,因为它会在包含它的每个文件中创建一组新的单独对象。对象的优点inline是总共只有一个。

但是,如果您只将这些constexpr值用作常量,您将不会注意到太大的差异。一个好的编译器可能会避免将常量存储在数据区域中。

正如 Tobi 所说,传递引用或指针并比较地址可能会产生影响。但也许您可以避免比较两个常量值的地址?

于 2018-01-03T15:59:04.963 回答