带有默认参数的类模板需要空尖括号<>

问题描述 投票:0回答:4

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);
}

这是编译器错误吗?

这个问题似乎表明它应该有效。

c++ templates function-templates default-template-argument
4个回答
7
投票

海湾合作委员会是对的。空模板参数列表,对于

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>

,而不指定模板参数列表,并且不在可以推导模板参数的上下文中。因此,这是不允许的。

    


1
投票
类模板参数推导 (CTAD) (C++17 起)

适用于声明。表达式 Test 不是声明,而是模板函数调用。

    


1
投票
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>&);
使模板实例化使用模板参数的默认类型,即
<>
    


0
投票
指南

int

© www.soinside.com 2019 - 2024. All rights reserved.