C++ 模板参数推导:三种不同的编译器三种不同的行为

C++ 模板参数推导:三种不同的编译器三种不同的行为,c++,templates,c++17,function-templates,C++,Templates,C++17,Function Templates,考虑以下演示程序 #include <iostream> template <class T1, class T2 = T1> struct A { }; template <template <class> class T> void f( const T<int> & ) { std::cout << "f( const T<int> & )\n"; } int main()

考虑以下演示程序

#include <iostream>

template <class T1, class T2 = T1>
struct A 
{
};

template <template <class> class T>
void f( const T<int> & )
{
    std::cout << "f( const T<int> & )\n";
}

int main()
{
    A<int> a;

    f( a );
    f<A>( a );
}

编译器<强> Visual C++ 2019 不编译第一个函数调用< /p>

f( a );
f<A>( a );
但是成功编译了第二个函数调用

f( a );
f<A>( a );
f(a);
<> P>这是一个编译器根据C++ 17(或C++ 20)标准执行的问题?< /p> < p>这是由C++ 17解决的。< /P> 请注意,g++在C++14模式(
-std=C++14
等)下拒绝程序(对
f
的两个调用)

Clang仅在非默认模式下接受您的程序,该模式由标志
-frelaxed template-args
启用,根据:

尽管此功能是缺陷报告的解决方案,但默认情况下在所有语言版本中都会禁用此功能,并且可以在Clang 4以后的版本中使用标志
-frelaxed template args
显式启用此功能。对标准的更改缺少对模板偏序的相应更改,从而导致合理且先前有效的代码出现歧义错误。这一问题预计将很快得到纠正

我不确定Clang到底关心哪些歧义错误,但一个看似合理的例子是


<> PMS>在C++ 14模式下(第二版代码为-> STD:C++ 14 14/代码>),拒绝在C++ C++模式下调用第二次调用<代码> f>代码>,接受C++ 17模式(<代码> -STD:C++17 < /COD>),证明它们认为P0522覆盖的第二调用是按不幸的是,他们似乎没有考虑到第一次调用的情况,其中模板参数是从函数参数推导而来的,这相当于CWG150中的第一种情况。我已经在开发者社区提交了一份报告。

IIRC有一份关于此的缺陷报告。现在没有时间尝试查找,但我会稍后再访问,看看是否找到或得到答复。