I am trying to create a templated can_stream struct that inherits from
std::false_type or std::true_type depending on whether operator<< is defined for type T.
#include <iostream>
struct S {
int i;
};
std::ostream& operator<< (std::ostream& os, S const& s) {
os << s.i << std::endl;
return os;
};
struct R {
int i;
};
template<
typename T,
typename Enable = void
> struct can_stream : std::false_type {
};
template<
typename T
> struct can_stream< T, decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >())) > : std::true_type {
};
int main() {
std::cout << can_stream< int >::value << std::endl;
std::cout << can_stream< S >::value << std::endl;
std::cout << can_stream< R >::value << std::endl;
}
I thought the above program would produce
1
1
0
because:
<< exists for both int and S (so decltype(...) is well formed).However, it produces:
0
0
0
Why?
operator
<<exists for bothintandS(sodecltype(...)is well formed).
But decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >())) is std::ostream&, where the default value for Enable is void.
There isn't match.
You can try with
template<
typename T // ........................................................................................VVVVVVVVV
> struct can_stream< T, decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()), void() ) > : std::true_type {
};
or, if you can use C++17, so std::void_t,
template<
typename T // ......VVVVVVVVVVVV
> struct can_stream< T, std::void_t<decltype( operator<<( std::declval< std::ostream& >(), std::declval< T const& >()))> > : std::true_type {
};
This solve the problem with S, because for S there is an operator<<() function. But doesn't works for int because, for int, the operator isn't defined as function. So, for int, you have to simulate the use
template<
typename T // ...........................................................VVVV
> struct can_stream< T, std::void_t<decltype( std::declval< std::ostream& >() << std::declval< T const& >() )> > : std::true_type {
};
See you if you prefer check the existence of a function operator<<() (but this doesn't works with int and other types with implicit operator <<) or if the operator << is concretely usable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With