簡體   English   中英

如何強制初始化靜態成員?

[英]How to force a static member to be initialized?

考慮這個示例代碼:

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; }
};

也在 Ideone 上。)

我希望dummy只要有Foo的具體實例化就會被初始化,我有Bar 這個問題(以及最后的標准報價)解釋得很清楚,為什么沒有發生。

[...] 特別是,靜態數據成員的初始化(以及任何相關的副作用)不會發生,除非靜態數據成員本身的使用方式要求靜態數據成員的定義存在。

有沒有辦法強制dummy被初始化(有效地調用register_沒有任何BarFoo實例(沒有實例,所以沒有構造函數詭計)並且Foo的用戶不需要以某種方式顯式聲明成員? 不需要派生類做任何事情的額外 cookie。


編輯找到一種對派生類影響最小的方法:

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

不過,我仍然希望派生類不必這樣做。 :|

考慮:

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;

我們可以使用一個基於必須用類實例化的聲明的簡單技巧:

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

請注意,某些編譯器會警告與 null 的比較; 如果需要,可以使用&foo==&foo(bool)&foo((void)&foo,true)避免。

另請注意,GCC 9.0–9.2不將此視為 odr-use

我想到了這樣的事情:

// 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;
}

由於可變參數,您可以在其中放置更多初始化,例如:

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

我最近碰到了這個。 官方解決方案將是顯式模板實例化,描述為here<\/a> 。

在上述情況下,語句應如下所示:

template class Foo::Bar;

您如何檢查 Bar 設置的值。 我更改了您的代碼並在 bar 中添加了另一個功能:

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

它給了我完全預期的結果。 我可能沒有正確理解,你到底想達到什么目的?

靜態成員在對象之間共享,因此必須在訪問時解析它們的范圍。 這就是為什么我們通過明確告訴編譯器這是我們要訪問的類的成員來使用 :: 的原因。

有沒有辦法在沒有任何 Bar 或 Foo 實例(沒有實例,所以沒有構造函數技巧)的情況下強制初始化(有效地調用 register_)?

這還不夠嗎?

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM