考虑以下演示程序。
#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 );
}
编译器gcc HEAD 10.0.1 20200编译程序成功,程序输出为
f( const T<int> & )
f( const T<int> & )
编译器 clang HEAD 11.0.0 既不编译函数 f
的第一次调用,也不编译函数 f
的第二次调用。它会发出类似的错误消息
prog.cc:25:5: error: no matching function for call to 'f'
f( a );
^
prog.cc:9:6: note: candidate template ignored: substitution failure: template template argument has different template parameters than its corresponding template template parameter
void f( const T<int> & )
^
1 error generated.
编译器 Visual C++ 2019 不编译第一个函数调用
f( a );
但是编译成功了第二个函数调用
f<A>( a );
那么问题来了,哪个编译器的行为符合 C++ 17(或者可能是 C++ 20)标准?
最佳答案
这是 CWG 150 ,由 DR P0522 解决,这是在 C++17 中。
请注意,g++ 在 C++14 模式(f
等)中拒绝程序(两次调用 -std=c++14
)。
Clang 仅在非默认模式下接受您的程序,使用标志 -frelaxed-template-template-args
启用, 根据 following rationale :
Despite being the resolution to a Defect Report, this feature is disabled by default in all language versions, and can be enabled explicitly with the flag
-frelaxed-template-template-args
in Clang 4 onwards. The change to the standard lacks a corresponding change for template partial ordering, resulting in ambiguity errors for reasonable and previously-valid code. This issue is expected to be rectified soon.
我不确定 Clang 究竟关心哪些歧义错误,但一个似是而非的例子是 this recent question .
至于 MSVC,它拒绝第二次调用 f
在 C++14 模式 ( -std:c++14
) 中,在 C++17 模式 ( -std:c++17
) 中接受它,表明他们认为根据 compliance table 第二次调用由 P0522 覆盖;不幸的是,他们似乎没有考虑第一次调用的情况,其中模板模板参数是从函数参数推导出来的,这相当于 CWG 150 中的第一种情况。我已经提交了 issue在开发者社区。p>
关于c++ - 模板模板参数扣: three different compilers three different behaviors,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60423780/