2017-06-28 3 views
0

C++は常に値の初期化子よりもリストの初期化子を優先しているようです。私の質問は、直接リストの初期化もサポートする型の値の初期化を強制する方法です。ここでは、最小限の非稼働例です。この例ではC++ 11の値の初期化子とリストの初期化子

#include <initializer_list> 

using namespace std; 

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

struct bar { 
    foo f{256}; 
}; 

、私はfoo(initializer_list<char>)ではなく、コンストラクタfoo(int)を使用して初期化するfをしたいと思います。しかし、GCCとClangの両方は、256がcharに対して大きすぎるため、C++仕様ではリスト初期化子を選択する必要があるため、コードを拒否します。明らかに、fooという2番目のコンストラクタをコメントアウトすると、問題が修正されます。フィールドfで値の初期化を使用するように、barを定義する最も簡単な方法は何ですか?私の実際の例ではコピーコンストラクタが存在しないので、理想的にはfのコピー初期化を避けることができます。明確にするために

更新

:もちろんそれはbarのすべての単一のコンストラクタで明示的にfを初期化することが可能です。しかし、私の質問は、メンバの初期化構文についてです。なぜなら、膨大な数のコンストラクタがある状況では、コード全体をコピーするのではなく、1つの場所で特定のフィールドを初期化する方が望ましいからです。

+0

コンストラクタを作成しますか? –

+0

'foo f(256);'と書いてください。 –

+0

'initializer_list 'が '{256}'の実行可能なコンストラクタである理由について説明したいと思います。また、コンパイラの振る舞いに基づいて仕様について推論することは安全ではありません。時々複数のコンパイラが同じことを間違ってしまうことがあります。 –

答えて

3

あなたは非コピー可能/移動可能にfooを必要とし、あなたの代わりに、コンストラクタで使用することができinitializer_listコンストラクタを持っているfooを必要としている限り、これはあなたが得る動作です。したがって、この問題を解決したい場合は、これらの事実の1つを変更する必要があります。

fooの定義をまったく変更できない場合は、あなたは嫌です。クラスを所有する誰にでも不平を言う。

秒という事実は、おそらく変更することが最も簡単ですが、でもそれは結果なしではありません。

struct il {}; 

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

この問題を完全に明確。 foo{256}は常に単一整数のコンストラクタを呼び出します。しかし、fooには技術的にinitializer_listコンストラクタがありません。あなたの代わりに値の初期化子リストでそれを呼び出すために、タグの種類ilを使用する必要があります。

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

これはブレース以上が必要ですが、本当の代替手段はありません。かかわらずfooがモバイルであるかどうかの

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

:C++ 17には、保証エリジオンは、あなたがこれを行うことができますことを

注意。

+0

'foo f = foo(256)'は、 'foo'のコピーコンストラクタが明示的に削除されていても、C++で動作することに興味があります。ありがとう。 – user3188445

関連する問題