尾随类模板参数未推断

twe*_*eej 13 c++ gcc templates type-deduction c++17

下面的代码无法使用gcc 7.1.0编译,它抱怨在main的第二行提供错误数量的模板参数.这个版本的GCC 应该实现类模板的模板参数推导.

我认为编译器应该能够推导出Bar的类模板参数T2,这意味着我不应该Bar<int, int>C++ 17草案的段落17.8.1.3中明确指定两个arguments(),它们说:"尾随模板可以推导出的参数(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
}
Run Code Online (Sandbox Code Playgroud)

son*_*yao 19

这是预期的行为; 与模板参数推导(对于函数模板)不同,类模板参数推导(自C++ 17以来)仅在未提供模板参数时有效.

仅在未提供模板参数的情况下才会执行类模板参数推导.如果指定了至少一个参数,则不进行演绎.

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
Run Code Online (Sandbox Code Playgroud)

这意味着对于您的示例,您无法利用类模板参数推断,并且必须指定所有模板参数.如果希望类模板参数推导生效,则必须指定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
}
Run Code Online (Sandbox Code Playgroud)