Alexander Morozov
Alexander Morozov

Reputation: 593

Why in this case decltype behavior is different from normal expression with libstdc++?

I found a case when expression inside decltype is processed successfully while the same expression outside decltype gives an error: see on Godbolt.

I'm checking if there is an overload of outputting into stream for a given type (operator <<) - by using decltype and type traits. But for libstdc++ from GCC < 7 decltype returns a correct type even for cases where there isn't such overload.

I tried Clang with libc++ - there is no such problem. Tried GCC 7.1 - no problem. But if I try GCC < 7 or Clang with libstdc++ from GCC < 7 - problem arise.

Basically:

class Foo {};

...

decltype(std::declval<std::ostringstream>() << std::declval<Foo>()) // gives std::ostringstream&

...

Foo foo;
std::ostringstream out;
out << foo; // gives an error (as it should, there is no overload for Foo)

So, why it's happening, what's wrong with libstdc++?

Upvotes: 0

Views: 74

Answers (1)

T.C.
T.C.

Reputation: 137301

std::declval<std::ostringstream&>() << std::declval<T const &>()
//                             ^                     ^^^^^^^^

Value categories matter. You are testing for the ability to stream a const T lvalue into a ostringstream lvalue.

In your original code, the << resolves to the until-recently-unconstrained << overload for rvalue streams. Without the constraint, the expression is always well-formed.

Upvotes: 2

Related Questions