I would like to overload the operator<< to allow it to work with shared_ptr.
template<typename T>
struct foo
{
virtual foo& operator<<(const T& e) = 0;
};
foo<int> f1;
f1 << 1;
std::shared_ptr<foo<int>> f2(new foo<int>());
f2 << 1;
My first try is the following, but the problem is that it with also enable the behavior for any class.
template<typename T, typename U>
const std::shared_ptr<T>& operator<<(const std::shared_ptr<T>& o, const U& e)
{
*o << e;
return o;
}
My second try is the following:
template<typename T, typename U>
const std::shared_ptr<foo<T>>& operator<<(const std::shared_ptr<foo<T>>& o, const U& e)
{
*o << e;
return o;
}
The problem with this solution is not work for types inheriting foo since T cannot be automatically deduced.
So I could skip U and use T instead, in which case T will be deduced from the second argument and the argument for o can be converted into foo<T>.
template<typename T, typename U>
const std::shared_ptr<foo<T>>& operator<<(const std::shared_ptr<foo<T>>& o, const T& e)
{
*o << e;
return o;
}
But then the following will not work:
struct c
{
};
struct a
{
a();
a(c); // implicit conversion
};
struct b
{
operator a(); // implicit conversion
};
auto f = std::make_shared<foo<a>>();
f << c; // doesn't work.
f << b; // doesn't work.
Any ideas on how make a working solution?
Some options, see the second live at https://ideone.com/26nqr
Given
Simple: template template arguments
Completer: SFINAE
The above doesn’t catch derived classes (case 2). To do that, I’d resort to