Я пытаюсь создать класс признаков типов, чтобы определить, может ли определенный тип T
быть потоковым с помощью <<
оператора std::ostream
. Я использую простой метод SFINAE.
В конечном итоге выражение, которое я пытаюсь оценить для отказа замены, следующее:
decltype(std::declval<std::ostream>() << std::declval<T>()) ;
Мое ожидание состоит в том, что, учитывая экземпляр T
типа T
и std::ostream
instance os
, если выражение os << t
плохо сформировано, должен произойти сбой замены.
Но, очевидно, сбой замены не возникает здесь, независимо от типа T
. И даже если я просто объявляю typedef
с использованием вышеприведенного выражения decltype
, вне контекста SFINAE, он с радостью компилируется, даже если T
не может использоваться с std::ostream
.
Например:
struct Foo { };
int main()
{
// This compiles fine using GCC 4.9.2
//
typedef decltype(
std::declval<std::ostream>() << std::declval<Foo>()
) foo_type;
}
Выше будет компилироваться с использованием GCC 4.9.2, чего я не ожидал, так как оператор <<
не перегружен для работы с типом Foo
. И, конечно, если я скажу:
std::cout << Foo();
... Я получаю ошибку компилятора. Итак, почему выражение decltype
выше даже вообще компилируется?