为什么在这种情况下 decltype 行为不同于 libstdc++ 的正常表达式?

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

我发现 decltype 内的表达式处理成功而 decltype 外的相同表达式给出错误的情况:see on Godbolt.

我正在检查给定类型 (operator <<) 是否存在输出到流的过载 - 通过使用 decltype 和类型特征。但是对于来自 GCC < 7 decltype returns 的 libstdc++,即使在没有这种重载的情况下也是正确的类型。

我用 libc++ 尝试了 Clang - 没有这样的问题。尝试过 GCC 7.1 - 没问题。但是,如果我尝试使用 GCC < 7 或 Clang 和来自 GCC < 7 的 libstdc++,就会出现问题。

基本上:

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)

那么,为什么会这样,libstdc++ 有什么问题?

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

价值类别很重要。您正在测试将 const T 左值流式传输到 ostringstream 左值的能力。

在您的原始代码中,<< 解析为右值流的 until-recently-unconstrained << 重载。没有约束,表达式总是合式的。