gcc 11.2 似乎无法编译这个:
template <typename T = int>
struct Test {};
template <typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test>(t);
}
但是没有问题与
template <typename T = int>
struct Test {};
template <typename T> void foo(T& bar) {}
int main()
{
Test t;
foo<Test<>>(t);
}
这是编译器错误吗?
这个问题似乎表明它应该有效。
海湾合作委员会是对的。空模板参数列表,对于
function模板,允许省略 ([temp.arg.explicit]/4)。在其他情况下,通常需要模板参数列表才能命名模板的特定专业化,即使它是空的。请参阅 simple-template-id、[temp.names]/1 的语法。 作为规则的有限例外,如果类模板的名称没有
模板参数列表出现在需要具体类型的上下文中,则它被称为“推导类类型的占位符”,这是仅允许在[dcl.type.class.deduct]中列出的特定上下文中使用。最常见的是像 <>
这样的变量声明,编译器将在 C++17 及更高版本中推导出
std::pair p("foo", 1)
。在您的代码中,您试图引用类模板的特定特化std::pair<const char*, int>
,而不指定模板参数列表,并且不在可以推导模板参数的上下文中。因此,这是不允许的。
适用于声明。表达式 Test
不是声明,而是模板函数调用。
foo<Test<>>(t);
) 指定为
Test
的模板参数,而不是类型(如类模板的实例)。您需要一个采用模板模板参数的函数来处理该问题。示例:
foo
在第二个片段中,
#include <type_traits>
template<template<class> class T, class U> // T = Test, U = deduced to int
void foo(T<U>& bar) {
std::cout << std::is_same<T<U>, Test<int>>::value << '\n'; // true
}
int main() {
Test t;
foo<Test>(t); // now ok
}
实例化
foo<Test<>>(t);
,因为foo<Test<int>>(Test<int>&);
使模板实例化使用模板参数的默认类型,即<>
。