Ich versuche, einen has_ostream_operator<T>
SFINAE-Test zu definieren, um zu überprüfen, ob ich einen bestimmten Typ cout kann. Ich habe es funktioniert, aber nur wenn ich in meiner Definition von has_ostream_operator
operator<<
als eine Methode statt als Infix-Operator aufrufen. Mit anderen Worten: das funktioniert:Warum muss ich Operator << als Methode für SFINAE aufrufen, um mit void_t zu arbeiten?
decltype(std::declval<std::ostream>().operator<<(std::declval<T>()))>
Dies gilt nicht:
decltype(std::declval<std::ostream>() << std::declval<T>())>
Testfall unten (kann auch bei http://coliru.stacked-crooked.com/a/d257d9d6e0f3f6d9 sehen). Beachten Sie, dass ich eine Definition von void_t aufgenommen habe, da ich nur in C++ 14 bin.
#include <iostream>
namespace std {
template<class...>
using void_t = void;
}
template<class, class = std::void_t<>>
struct has_ostream_operator : std::false_type {};
template<class T>
struct has_ostream_operator<
T,
std::void_t<
decltype(
std::declval<std::ostream>().operator<<(std::declval<T>()))>>
: std::true_type {};
struct Foo {};
template<class X>
void print(
const X& x,
std::enable_if_t<has_ostream_operator<X>::value>* = 0)
{
std::cout << x;
}
template<class X>
void print(
const X&,
std::enable_if_t<!has_ostream_operator<X>::value>* = 0)
{
std::cout << "(no ostream operator<< implementation)";
}
int main()
{
print(3); // works fine
print(Foo()); // this errors when using infix operator version
return 0;
}
Diese Definition von 'void_t' induziert nicht definiertes Verhalten ([namespace.std]/1). – Columbo
Sind Sie sicher, dass Sie alle diese Probleme durchgehen müssen, um einen Fehler bei der Kompilierung in einen Laufzeitfehler zu konvertieren? Ich bin sehr neugierig auf den tatsächlichen Anwendungsfall. Ist Ihr Ziel wirklich in der Lage zu sein, 'print (x)' für jedes 'x' zu schreiben und diese Laufzeitnachricht immer dann angezeigt zu bekommen, wenn' x' nicht druckbar ist? – JorenHeit