Sto provando a definire un test SFINAE has_ostream_operator<T>
per verificare se posso cout un determinato tipo. Ho funzionato, ma solo se nella mia definizione di has_ostream_operator
chiamo operator<<
come metodo piuttosto che come operatore infisso. In altre parole questo funziona:Perché devo chiamare l'operatore << come metodo per SFINAE per lavorare con void_t?
decltype(std::declval<std::ostream>().operator<<(std::declval<T>()))>
Questo non lo fa:
decltype(std::declval<std::ostream>() << std::declval<T>())>
caso di prova di seguito (può anche vedere di http://coliru.stacked-crooked.com/a/d257d9d6e0f3f6d9). Nota che ho incluso una definizione di void_t dato che sono solo su C++ 14.
#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;
}
Tale definizione di 'void_t' induce un comportamento indefinito ([namespace.std]/1). – Columbo
Sei sicuro di voler risolvere questo problema per convertire un errore in fase di compilazione in un errore di runtime? Sono molto curioso del vero caso d'uso. Il tuo obiettivo è davvero essere in grado di scrivere 'print (x)' per qualsiasi 'x' e mostrare il messaggio di runtime quando' x' risulta non essere stampabile? – JorenHeit