c++ - 模板模板参数扣: three different compilers three different behaviors

标签 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()
{
    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在开发者社区。

关于c++ - 模板模板参数扣: three different compilers three different behaviors,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60423780/

相关文章:

c++ - 为什么在英特尔编译器上将 OpenMP 的 firstprivate 与 std::vector 结合使用时会出现未定义的行为?

c++ - 声明模板函数以接受任何容器,但只接受一个包含的类型

c++ - 为什么 void sorting(int *[], int) 会导致 "Unable to read memory"?

C++模板函数将字符串拆分为数组

c# - 如何在 Windows 中开发服务器

c++ - 构造一个改变混合基类的类型

c++ - 模板类的非模板函数友元

c++ - const char* 不能用作 std::char_traits<char>::length 的常量值

c++ - std::visit for variant 无法在 clang 5 下编译

c++ - C++ 编译器能否对用于返回值的命名 const 变量执行 RVO?