Ezekeel
Ezekeel

Reputation: 43

Check whether ostream << T is defined for class T

Is there a way to check whether ostream << T is defined for a class T and use that info in deciding whether to construct a template?

For example, let us say I got some wrapper class around different types of T

template<class T>
Wrapper
{
public:

    T m_value;

    Wrapper(const T & value) : m_value{ value } { }
};

and I want to define an operator<<() friend function for printing to ostream

template<class T>
ostream & operator<<(ostream & out, const Wrapper<T> & wrapper)
{
    out << wrapper.value;

    return out;
}

Is there a way to only construct that template for types T which have ostream << T defined?

Upvotes: 4

Views: 215

Answers (1)

Sam Varshavchik
Sam Varshavchik

Reputation: 118350

A blueprint for doing something like that is to start with this:

#include <utility>
#include <iostream>

template<typename T, typename=void>
struct can_output_to_ostream : public std::false_type {};

template<typename T>
struct can_output_to_ostream<T, std::void_t
               <decltype(std::declval<std::ostream &>() <<
                     std::declval<T &&>())>>
    : public std::true_type{};


struct x {};

int main()
{
    std::cout << can_output_to_ostream<int>::value << std::endl;
    std::cout << can_output_to_ostream<x>::value << std::endl;
}

std::void_t is C++17, but a brief search will find examples of implementing it in earlier C++ revisions.

The output of this example is:

1
0

because you can << an int, but there's no such overload defined for x.

In your case, you can use this example and have your wrapper class inherit from a implements_output_to_ostream class that's defined in the similar manner. The default implementation does nothing, and the one for a << capable class implements the << operator accordingly.

Your Wrapper class inherits from implements_output_ostream. Perhaps your Wrapper class will provide its own << method that passes its member to the parent class's method, which will be fully defined for a << capable class, and undefined otherwise, causing a compilation error if an attempt is made to reference it for a class that does not implement the << overload.

Upvotes: 4

Related Questions