2013-07-10 1 views
14

私は、テンプレート型推論が失敗しながらブレース初期化子与え、autoは、std::initializer_listの種類を推測します、ということを理解:括弧で囲まれたイニシャライザで、自動とテンプレートの種類の差異が異なるのはなぜですか?

auto var = { 1, 2, 3 }; // type deduced as std::initializer_list<int> 

template<class T> void f(T parameter); 

f({ 1, 2, 3 });   // doesn't compile; type deduction fails 

これはC++ 11標準で指定された場合、私も知っている:14.8。 2.5/5箇条書き5:は、型推論の挙動の違いが存在する理由を私は知っているか理解していない何

[It's a non-deduced context if the program has] A function parameter for which the associated argument is an initializer list (8.5.4) but the parameter does not have std::initializer_list or reference to possibly cv-qualified std::initializer_list type. [ Example:

template void g(T);

g({1,2,3}); // error: no argument deduced for T

end example ]

です。 C++ 14 CDの仕様はC++ 11と同じですので、おそらく標準化委員会はC++ 11の動作を欠陥として見なさないでしょう。

なぜautoは、括弧で囲まれた初期化子の型を推測しますが、テンプレートは許可されていませんか? "これは理由があるかもしれない"という推測的な説明は面白いですが、私は特にを知っている人からの説明に興味があります。

+0

あなたが考え出したことについて最近質問された別のSOの質問がありました。なぜそれがあるのか​​もしれない。 – chris

+2

それを見つけました。なぜ討論が1つのコメントであるのかという唯一の真実ですが、あなたは見てみることができます:http://stackoverflow.com/questions/17496268/type-in​​ference-with-rvalue-initializer-list – chris

+3

[Scott Meyers](http: /scottmeyers.blogspot.cz/2013/07/when-decltype-meets-auto.html): "なぜ、' auto'とテンプレートの型減算が同じでないのか分かりません。 * "。 –

答えて

0

まず第一に、フォームの投機的な説明です。これは、あなたがそれを呼び出す理由である可能性があります。

{1,2,3}は、std::initializer_list<int>だけでなく、コンストラクタなしで初期化することもできます。たとえば、

#include <initializer_list> 

struct x{ 
    int a,b,c; 
}; 

void f(x){ 

} 
int main() { 
    f({1,2,3}); 
} 

が正しいコードです。

#include <initializer_list> 

struct x{int a,b,c;}; 

void f(x){ 

} 
int main() { 
    auto il = {1, 2, 3}; 
    f(il); 
} 

エラーがある:それは以下のコードを見てみましょうinitializer_listではないことを示すために「?違いは何ですか」という質問に、今

prog.cpp: In function ‘int main()’: 
prog.cpp:10:9: error: could not convert ‘il’ from ‘std::initializer_list<int>’ to ‘x’ 

とをコーダは、明示的関数テンプレートの場合には、彼は彼が別のタイプを使用していることを確認することができるがauto

を使用して「これは何だが、それがされるタイプは重要ではありません」と言ったので

auto x = {1, 2, 3};コードでは、タイプを決定するためにOKです。あいまいなケースでエラーを防ぐのは良いことです(C++スタイルのようには見えません)。

特に1つの機能があった場合にはf(x)とし、それをテンプレート1に変更しました。プログラマはそれをxとして使用するように書きました。そして、他の型のために新しい関数を追加した後、それはわずかに変化して完全に別の型を呼び出します。

+1

「自動」とは「タイプが重要ではない」という意味ですが、「テンプレート」とは何か違うことを言っているのか分かりません。いずれの場合も、推測される型がプログラマーの意図したものではないリスクがあります。 – KnowItAllWannabe

+0

私は第2のコードを理解していません。あなたは ''イニシャライザリストではないことを表示しますが、 '{1,2,3}'の例ではイニシャライザリストなので、エラーが発生します... – user463035818

+0

私は最初のコードでinitializer_listではないことを示しています。それはinitialzer_listのときに動作しないので – RiaD

13

控除(私は担当の男との議論に覚えている2)将来の言語拡張について

  • 心配をしないテンプレートには2つの重要な理由(あなたはできる複数の意味がありますがあります。発明された - 初期化されたinitリストの関数引数のための完璧な転送を導入したいのであれば、どうですか?)

  • ブレースは、時には正当、Tinitializer_list<int>になく左側にvector<int>に右側に推定される場合

template<typename T> 
void assign(T &d, const T& s); 
int main() { 
    vector<int> v; 
    assign(v, { 1, 2, 3 }); 
} 

依存する関数のパラメータを初期化することができこれは、矛盾した議論の控除のために機能しないでしょう。

autoからinitializer_list<T>への控除は議論の余地があります。それを取り除く(そして、{ }または{a, b}で初期化を禁止し、{a}aの型に推論するようにする)C++の提案があります。