【问题标题】:Can I define a static constexpr data member only for certain specializations?我可以仅为某些专业定义静态 constexpr 数据成员吗?
【发布时间】:2016-05-01 06:59:46
【问题描述】:

以下程序运行良好。

#include <iostream>
#include <type_traits>

template <typename DummyT = void>
struct wrapper
{
  static_assert(std::is_same<void, DummyT>::value, "Only void, please");
  static constexpr char text[] = "some string constant";
};

template <typename DummyT>
constexpr char wrapper<DummyT>::text[];

int
main()
{
  std::cout << wrapper<>::text << '\n';
}

但是,当我只为wrapper&lt;void&gt; 定义wrapper::text 时,

template <>
constexpr char wrapper<void>::text[];

然后 GCC 5.3.0 给了我这个链接器错误

/tmp/ccnGx3EP.o: In function `main':
main.cxx:(.text+0x5): undefined reference to `wrapper<void>::text'
collect2: error: ld returned 1 exit status

Clang 3.7.1 给了我这个错误。

main.cxx:12:31: error: declaration of constexpr static data member 'text' requires an initializer
constexpr char wrapper<void>::text[];
                              ^
1 error generated.

我想知道为什么只为实际使用的专业提供定义是不够的。并不是说它非常有用,因为 static constexpr 成员必须在 class 定义中进行初始化,所以无论如何我都无法将其专门用于定义,但我可能希望将其保留为未定义。

【问题讨论】:

  • 显式特化有效地替换了主模板中的声明/定义。
  • @T.C.我假设静态数据成员的类内初始化不是定义。那么模板主体中的声明+初始化不应该适用于数据成员的所有规范化隐式实例化类模板吗?
  • @T.C.是的,我的直觉是对的:coliru.stacked-crooked.com/a/597464c14d48071f。所以,他的问题是他不能在不提供初始化程序的情况下提供定义的特化,因为后者只声明了特化。但如果他做后者,他将有两个初始化器。

标签: c++ templates c++14 constexpr one-definition-rule


【解决方案1】:

轻松:

template <typename DummyT = void>
struct wrapper
{
  static_assert(std::is_same<void, DummyT>::value, "Only void, please");
};

template <>
struct wrapper<void>
{
  static constexpr char text[] = "some string constant";
};

constexpr char wrapper<void>::text[];

wrapper&lt;&gt;wrapper&lt;void&gt; 都可以工作,而任何其他参数都将失败并返回 static_assert

【讨论】:

  • 虽然这是一个我没有想到的好技巧,但不幸的是,当#included 进入多个翻译单元并链接在一起时,它会导致多重定义错误,从而减少广告荒谬首先使用template 的目的。
  • 如果行“constexpr char wrapper::text[];”,多重定义问题就会消失被移动到一个 cpp(而不是头文件)文件中。这可以是编译中使用的任何 cpp 文件,包括可能包含在其自己的 cpp 文件中,该文件仅包含 2 行代码(#include 语句加上定义本身) - 当需要提供静态成员时,我个人多次使用后一种方法模板类的定义。
猜你喜欢
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
  • 2013-05-03
  • 1970-01-01
相关资源
最近更新 更多