I have a friend function template operator<<
that works with both gcc and clang but not with 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
}
I want to know which compiler has the correct behavior according to the c++ standard. The msvc error says:
<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)
3
1 Answer
This is a MSVC bug and has nothing to do with the operator<<
at all.
Just mentioning Foo<U>
anywhere with U
being a template parameter causes the error because MSVC tries to check validity of std::enable_if_t< T{1}, int>
immediately, even though no concrete type for U
/T
is known yet. This then fails.
MSVC doesn’t correctly recognize that std::enable_if_t< T{1}, int>
is a dependent type and therefore shouldn’t be checked until after a concrete U
/T
is substituted.
See https://godbolt.org/z/ncb3va3ro for a reduced example:
template< typename T, std::enable_if_t< T{1}, int> =0 >
class Foo
{
};
template<typename R>
using U = Foo<R>; // <- same error here
3
-
Isn't there a bug filed to msvc for the same?
– Alan14 hours ago
-
1
@Alan I don't know. I haven't checked developercommunity.visualstudio.com/home.
– user1773252214 hours ago
-
1
I think it's an MSVC bug to do with enable_if. Here's a similar example stackoverflow.com/questions/74902168
15 hours ago
There's no point asking about downvotes, especially a single one. People may not understand something and downvotes, they have a right to a single vote. Even if they don't understand due to a fault of their own, it's still their right to vote. Asking for explanations is at best going to be ignored, or at worse draw out long fruitless arguments. Discussing downvotes is a waste of time for everyone.
15 hours ago
As a workaround, making it a type parameter
typename = std::enable_if_t< T{1}>
seems to compile.11 hours ago