Ala*_*lan 12 c++ templates language-lawyer
我有一个友元函数模板operator<<,它可以与 gcc 和 clang 一起使用,但不能与 msvc 一起使用。
#include <iostream>
#include <type_traits>
template< typename T, std::enable_if_t< T{1}, int> =0 >
class Foo
{
template< typename Ar, typename R>
friend Ar& operator<<(Ar& os, const Foo<R>& foo)
{
return os;
}
};
int main()
{
Foo<int> i;
std::cout << i; //works with gcc and clang but does not compile with msvc
}
Run Code Online (Sandbox Code Playgroud)
我想知道哪个编译器根据 C++ 标准具有正确的行为。msvc 错误说:
<source>(4): error C2972: 'Foo': template parameter 'unnamed-parameter': the type of non-type argument is invalid
<source>(6): note: see declaration of 'Foo'
<source>(4): note: the template instantiation context (the oldest one first) is
<source>(11): note: see reference to class template instantiation 'Foo<T,__formal>' being compiled
<source>(15): error C2679: binary '<<': no operator found which takes a right-hand operand of type 'Foo<int,0>' (or there is no acceptable conversion)
Run Code Online (Sandbox Code Playgroud)
use*_*522 14
这是一个 MSVC 错误,与完全无关operator<<。
只要Foo<U>在任何地方U提及模板参数就会导致错误,因为 MSVC 会尝试std::enable_if_t< T{1}, int>立即检查 / 的有效性,即使尚不知道U/的具体类型。T然后这会失败。
MSVC 无法正确识别这是一个依赖类型,因此在替换具体的/std::enable_if_t< T{1}, int>之前不应进行检查。UT
请参阅https://godbolt.org/z/ncb3va3ro了解简化示例:
template< typename T, std::enable_if_t< T{1}, int> =0 >
class Foo
{
};
template<typename R>
using U = Foo<R>; // <- same error here
Run Code Online (Sandbox Code Playgroud)