2017-06-28 51 views
0

從經驗上看,C++總是比列表初始值設定項更喜歡列表初始值設定項。我的問題是如何強制一個類型的值初始化,它也支持直接列表初始化。下面是一個最小的非工作例如:C++ 11值初始值設定項vs列表初始值設定項

#include <initializer_list> 

using namespace std; 

struct foo { 
    foo(int) {} 
    foo(initializer_list<char>) {} 
}; 

struct bar { 
    foo f{256}; 
}; 

在這個例子中,我想f使用構造foo(int)而非foo(initializer_list<char>)進行初始化。然而,GCC和Clang都拒絕了代碼,因爲256對於char來說太大了,這意味着C++規範要求選擇列表初始值設定項。明顯地註釋掉foo的第二個構造函數修復了這個問題。定義bar以便在字段f上使用值初始化的最簡單方法是什麼?理想情況下,我可以避免複製初始化f,因爲在我的實例中沒有複製構造函數。

更新

澄清:當然有可能在bar每一個構造函數中明確初始化f。但我的問題特別是關於成員初始化語法,因爲在具有大量構造函數的情況下,最好只在一個地方初始化某些字段,而不是全部複製代碼。

+0

寫一個構造函數? –

+0

只要寫'foo f(256);'。 –

+0

我想看看爲什麼'initializer_list '是'{256}'的可行構造函數的解釋。基於編譯器行爲推斷關於規範的東西也是不安全的。有時候多個編譯器會得到相同的錯誤。 –

回答

3

只要你需要foo是非可複製/移動,你需要foo有一個initializer_list構造,可以用來代替構造函數,這是你的行爲。因此,如果你想解決這個問題,你必須改變其中的一個事實。

如果根本無法更改foo的定義,那麼就搞砸了。向任何擁有課堂的人投訴。

第二個事實是可能是最容易改變,但即使這樣也不會沒有後果:

struct il {}; 

struct foo { 
    foo(int) {} 
    foo(il, initializer_list<char>) {} 
}; 

這完全消除歧義的問題。 foo{256}將始終調用單個整數構造函數。但是,foo在技術上沒有initializer_list構造函數;你,而不是必須使用的標籤類型il與值的初始化列表來調用它:

foo f{il{}, {/*actual list*/}}; 

這需要更多的支撐,但目前還沒有真正的選擇。

注意,在C++ 17,保證省音讓你這樣做:

struct bar { 
    foo f = foo(256); 
}; 

不管foo是移動與否。

+0

有趣的是,即使明確刪除了「foo」的拷貝構造函數,在'foo f = foo(256)'中也可以在C++ 17中工作。謝謝。 – user3188445

相關問題