Xeo*_*Xeo 20 c++ templates static-members static-initialization
考虑这个示例代码:
template<class D>
char register_(){
return D::get_dummy(); // static function
}
template<class D>
struct Foo{
static char const dummy;
};
template<class D>
char const Foo<D>::dummy = register_<D>();
struct Bar
: Foo<Bar>
{
static char const get_dummy() { return 42; }
};
Run Code Online (Sandbox Code Playgroud)
(也在Ideone上.)
我期望dummy得到尽快初始化为有一个具体的实例Foo,我有Bar.这个问题(以及最后的标准引用)解释得很清楚,为什么没有发生.
[...]特别是,除非静态数据成员本身以需要静态数据成员的定义存在的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用).
有没有办法强制 dummy初始化(有效调用register_)没有任何实例Bar或Foo(没有实例,所以没有构造函数欺骗),没有用户Foo需要以某种方式明确说明成员?额外的cookie,不需要派生类做任何事情.
编辑:找到一种方法,对派生类的影响最小:
struct Bar
: Foo<Bar>
{ // vvvvvvvvvvvv
static char const get_dummy() { (void)dummy; return 42; }
};
Run Code Online (Sandbox Code Playgroud)
虽然,我仍然喜欢派生类不必这样做.:|
Joh*_*itb 11
考虑:
template<typename T, T> struct value { };
template<typename T>
struct HasStatics {
static int a; // we force this to be initialized
typedef value<int&, a> value_user;
};
template<typename T>
int HasStatics<T>::a = /* whatever side-effect you want */ 0;
Run Code Online (Sandbox Code Playgroud)
在没有引入任何成员的情况下也可以:
template<typename T, T> struct var { enum { value }; };
typedef char user;
template<typename T>
struct HasStatics {
static int a; // we force this to be initialized
static int b; // and this
// hope you like the syntax!
user :var<int&, a>::value,
:var<int&, b>::value;
};
template<typename T>
int HasStatics<T>::a = /* whatever side-effect you want */ 0;
template<typename T>
int HasStatics<T>::b = /* whatever side-effect you want */ 0;
Run Code Online (Sandbox Code Playgroud)
我们可以使用一个基于必须用类实例化的声明的简单技巧:
\n\ntemplate<\xe2\x80\xa6>\nstruct Auto {\n static Foo foo;\n static_assert(&foo);\n};\ntemplate<\xe2\x80\xa6> Foo Auto::foo=\xe2\x80\xa6;\nRun Code Online (Sandbox Code Playgroud)\n\n请注意,某些编译器会警告与 null 的比较;&foo==&foo如果需要,可以使用、(bool)&foo或 来避免((void)&foo,true)。
另请注意,GCC 9.0\xe2\x80\x939.2 don\xe2\x80\x99t 将此视为 odr-use。
\n