I'm trying to create a type traits class to determine if a particular type T
can be streamed via the <<
operator of an std::ostream
. I'm using a straightforward SFINAE technique.
Ultimately, the expression I attempt to evaluate for substitution failure is:
decltype(std::declval<std::ostream>() << std::declval<T>()) ;
My expectation is that, given an instance t
of type T
and an std::ostream
instance os
, if the expression os << t
is ill-formed, a substitution failure should occur.
But apparently substitution failure never occurs here regardless of the type T
. And even if I just declare a typedef
using the above decltype
expression, outside the context of SFINAE, it happily compiles, even if T
cannot be used with std::ostream
.
For example:
struct Foo { };
int main()
{
// This compiles fine using GCC 4.9.2
//
typedef decltype(
std::declval<std::ostream>() << std::declval<Foo>()
) foo_type;
}
The above will compile fine using GCC 4.9.2, which is not what I expected since the <<
operator is not overloaded to work with a type Foo
. And of course, if I say:
std::cout << Foo();
... I get a compiler error. So why does the decltype
expression above even compile at all?