Я пытаюсь создать класс признаков типов, чтобы определить, может ли определенный тип 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 выше даже вообще компилируется?