【发布时间】: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<void> 定义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