如何强制静态成员初始化?

时间:2011-06-21 06:00:59

标签: 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; }
};

Also on Ideone。)

我希望dummyFoo的具体实例化后立即初始化,我与Bar进行了实例化。 This question(以及最后的标准引用)非常明确地解释了为什么没有发生这种情况。

  特别是,除非静态数据成员本身以需要定义静态数据成员的方式使用,否则不会发生静态数据成员的初始化(以及任何相关的副作用)。存在。

有没有办法强制 dummy进行初始化(有效地调用register_,不用 Bar的任何实例或Foo(没有实例,所以没有构造函数欺骗)并且没有Foo的用户需要以某种方式明确说明成员?额外的cookie,不需要派生类做任何事情。


修改Found a way,对派生类的影响最小:

struct Bar
    : Foo<Bar>
{   //                              vvvvvvvvvvvv
    static char const get_dummy() { (void)dummy; return 42; }
};

尽管如此,我仍然希望派生类不必这样做。 :|

5 个答案:

答案 0 :(得分:9)

考虑:

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;

也可以不引入任何成员:

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;

答案 1 :(得分:1)

我们可以使用基于必须使用类实例化的声明的简单技巧:

template<…>
struct Auto {
  static Foo foo;
  static_assert(&foo);
};
template<…> Foo Auto::foo=…;

请注意,一些编译器警告比较为null。可以通过&foo==&foo(bool)&foo((void)&foo,true)来避免这种情况。

还要注意,GCC 9 doesn’t count this as an odr-use

答案 2 :(得分:0)

  

有没有办法强制虚拟初始化(有效地调用register_)而没有任何Bar或Foo实例(没有实例,所以没有构造函数欺骗)?

这不足够吗?

std::cout << Foo<int>::dummy;

答案 3 :(得分:0)

您如何检查Bar设置的值。 我改变了你的代码并在bar中添加了另一个函数:

....
static char const get_dummy(int){return Foo<Bar>::dummy;}
....

它给了我完全预期的结果。我可能没有正确理解,你到底想要达到什么目的?

静态成员在对象之间共享,因此必须在访问时解析其范围。这就是为什么我们使用::通过明确告诉编译器这是我们想要访问的类的成员。

答案 4 :(得分:0)

我想到了类似的事情:

// in some c++ file (to make i with internal linkage)
static int i = init_dummy(Foo<int>::dummy);

其中init_dummy的定义如下:

int init_dummy(...)
{
  return 1;
}

由于变量args,您可以在其中添加更多初始化,如:

static int i = init_dummy(Foo<int>::dummy, Foo<double>::dummy, Foo<whatever>::dummy);
相关问题