std::enable_if_t 适用于 gcc 和 clang,但不使用 msvc 进行编译

std::enable_if_t works with gcc and clang but does not compile with msvc

提问人:Alan 提问时间:10/16/2023 最后编辑:user3840170Alan 更新时间:10/16/2023 访问量:678

问:

我有一个朋友函数模板,它适用于 gcc 和 clang,但不适用于 msvc。operator<<

#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
}

我想知道根据 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)
C++ 模板 language-lawyer

评论

1赞 cigien 10/16/2023
我认为这是与enable_if有关的 MSVC 错误。下面是一个类似的示例 stackoverflow.com/questions/74902168
0赞 BoP 10/16/2023
作为一种解决方法,使其成为类型参数似乎可以编译。typename = std::enable_if_t< T{1}>
1赞 HolyBlackCat 10/16/2023
考虑使用 ,它更具可读性,并且可能没有错误。requires

答:

14赞 user17732522 10/16/2023 #1

这是一个 MSVC 错误,与 完全无关。operator<<

只要在任何地方提到作为模板参数会导致错误,因为 MSVC 会尝试立即检查 的有效性,即使尚无 / 的具体类型。然后,这将失败。Foo<U>Ustd::enable_if_t< T{1}, int>UT

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

评论

1赞 user17732522 10/16/2023
@Alan我不知道。我没有检查 developercommunity.visualstudio.com/home
6赞 Fedor 10/16/2023
刚刚报道:developercommunity.visualstudio.com/t/......