Check if a stream can be an instance of type
I've underestimated this meta feature for a long time. This seems to work, but I suspect it contains UB, when it checks for the size of the reference type, maybe undefined? Is there a problem with this meta function?
template <class S, class C, typename = void>
struct is_streamable : ::std::false_type { };
template <class S, class C>
struct is_streamable<S,
C,
decltype(void(sizeof(decltype(::std::declval<S&>() <<
::std::declval<C const&>()))))
> : ::std::true_type
{
};
EDIT: The motivation behind my question (and concern) was this question . Why didn't he use a similar trick (checking the size of the reference type)?
source to share
when it checks the size of the reference type is it possibly undefined?
It never calls UB. This will simply lead to a loss of deduction (according to [temp.deduct] / 8), resulting in the primary template being created. [Expr.sizeof]:
When applied to a reference or reference type, the result is the size of the reference type.
The operator
sizeof
does not apply to an expression that has [...] incomplete type [...].
But still incomplete ostream
is considered "streamable" for a string
if the global is operator<<
overloaded.
To fix this, define a partial specialization as
template <class S, class C>
struct is_streamable<S, C,
decltype(void( std::declval<S&>() << std::declval<C const&>() ))
> : ::std::true_type
{};
Demo .
source to share