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)?

+3


source to share


1 answer


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 .

+2


source







All Articles