2017-08-06 3 views
12

以下のコードは、gcc 7.1.0でコンパイルできません。これは、mainの2行目に間違った数のテンプレート引数を指定していると文句を言います。 GCCのこのバージョンは、supposed to implementクラステンプレートのテンプレート引数の控除です。末尾のクラスのテンプレート引数が導出されない

私は、コンパイラは私が明示的に引数(Bar<int, int>)の両方を指定する必要はありませんことを意味バーのクラステンプレート引数T2、言うC++17 draftの与えられた段落17.8.1.3を推定することができるはずだと思います」推論可能なテンプレート引数(17.8.2)またはデフォルトのテンプレート引数から得られるテンプレート引数は、明示的なテンプレート引数のリストから省略することができます。

私は間違っていますか?コンパイラが間違っていますか?これは見落としや意図的なデザインですか?

template <typename T> 
struct Foo { 
    Foo(T t) {} 
}; 

template <typename T1, typename T2> 
struct Bar { 
    Bar(T2 t) {} 
}; 

template <typename T1, typename T2> 
void bar(T2 t) {} 

int main(int argc, char **argv) { 

    Foo(42); // Works 

    Bar<int>(42); // Fails to compile with "wrong number of 
        // template arguments (1, should be 2)" 

    bar<int>(42); // Works 
} 

答えて

17

これは予期される動作です。 template argument deduction(関数テンプレートの場合)と異なり、class template argument deduction(C++ 17以降)はテンプレート引数が指定されていない場合にのみ機能します。

クラステンプレートの引き算は、引数が提供されていない場合にのみ実行されます。 少なくとも1つの引数が指定されている場合は、 の控除は行われません。あなたの例のためにあなたがクラステンプレート引数控除を利用して、すべてのテンプレート引数を指定する必要がないことを意味し

std::tuple t(1, 2, 3);    // OK: deduction 
std::tuple<int,int,int> t(1, 2, 3); // OK: all arguments are provided 
std::tuple<int> t(1, 2, 3);   // Error: partial deduction 

。クラステンプレート引数の控除を有効にするには、noneを指定する必要がありますが、テンプレートパラメータT1を推測することはできません。

一方、次のコードが機能します。

template <typename T1, typename T2> 
struct Bar { 
    Bar(T1, T2) {} // make it possible to deduce T1 
}; 

int main(int argc, char **argv) { 
    Bar bar(42, 42); // take advantage of class template argument deduction 
} 
+0

回答とドキュメントへのリンクありがとうございます。私はまだこれがなぜその理由であるかに興味があります。なぜこれが意図的に防止されるのかはわかりませんので、将来のバージョンの言語でこれが可能かどうかは疑問です。 – tweej

+0

これのサポートは、将来のバージョンの言語で提案される予定です。 #CppCon2017 – tweej

関連する問題