【问题标题】:Defining global constexpr variables in anonymous namespace the same as making them inline?在匿名命名空间中定义全局 constexpr 变量与使它们内联相同?
【发布时间】:2018-01-03 13:02:00
【问题描述】:

跟进Why does cppreference define type_traits xxx_v shortcuts as inline constexpr and not just constexpr?,如果我创建自己的类型特征并希望避免 ODR 违规并希望它与 C++17 之前的项目兼容,则将 xxx_v 快捷方式放在匿名命名空间中,与明确声明它内联?

例如,从Check traits for all variadic template arguments 中获取all_true,使用 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;
}

【问题讨论】:

  • 未命名的命名空间提供了内部链接中的所有内容...并且all_true_v 无论如何都有内部链接,原因与@Oliv 在您的另一个问题中引用的原因相同(C++ 14 中的相同项目符号)。所以你提供的两个代码 sn-ps 根本不兼容。
  • @StoryTeller 当然。我的混搭。

标签: c++ c++17 inline-variable


【解决方案1】:

考虑

    bool const* g_b= &all_true_v<true>;

inline constexpr 版本的每个翻译单元中的地址都相同,但namespace {} 版本的地址不同。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-08
      • 1970-01-01
      • 2012-03-13
      • 2016-02-25
      • 2015-04-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多