I'm a bit annoyed with compilation errors which arise when I try to write std::cout << x, and left shift operator it not defined for x. Can't convert x to this, can't convert x to that... Several screens of useless error messages.
I want to specialize operator<<(std::ostream&, const T&) for all types which do not yet have such operator defined. Inside I could put a, say, static assert and make compilation error message much clearer than it is now.
My first attempt was the following.
template<typename T, typename = void>
struct Has : public std::false_type {};
template<typename T>
struct Has<T, decltype(void(
std::declval<std::ostream&>() << std::declval<T>()
))> : public std::true_type {};
template<typename T>
auto operator<<(std::ostream& out, const T&)
-> typename std::enable_if<
!Has<T>::value,
std::ostream&>::type
{
return out << "my operator";
}
It fails to compile because maximum template depth is exceeded. Indeed, my operator<< calls to Has specialization which in order calls to operator<<, where my overload is examined once again, so on, so on, so on.
The simplest version doesn't work as well: ambiguous overload for std::ostream& << const char*. Well, expected.
template<typename T>
std::ostream& operator<<(std::ostream& out, const T&)
{
return out << "my operator";
}
How can I accomplish the task? Or, in general, how can I define the function for all argument types but for those which can already be passed to the function?
Aucun commentaire:
Enregistrer un commentaire