Reputation: 28252
I want to write a generic printing template, so a more specific wording of the question would be: how can I determine if some operator<<
method is overloaded for a type?
Upvotes: 4
Views: 432
Reputation: 172894
SFINAE can help you to check if a certain method has been provided.
#include <iostream>
struct Generic {};
struct Printable{};
std::ostream& operator<<(std::ostream& o, const Printable& t) {
return o;
}
// SFINAE test
typedef char one;
typedef struct { char a[2]; } two;
template <typename T> static one printable_test(std::ostream&o, decltype (o << T{}, 0) ) ;
template <typename T> static two printable_test(...);
template <typename T> bool printable_with(std::ostream& o) {
return sizeof(printable_test<T>(o, 0)) == sizeof(one);
}
int main() {
std::cout << std::boolalpha << printable_with<Generic>(std::cout) << std::endl;
std::cout << std::boolalpha << printable_with<Printable>(std::cout) << std::endl;
return 0;
}
Some explanations.
There're 2 overloaded function templates printable_test
, the overload resolution result of invoking of them in printable_with()
will tell the result.
The 1st version takes decltype (o << T{}, 0)
as its 2nd parameter, which is valid only when o << T{}
is valid, i.e. operator<<
on T
is provided, and then decltype
will take 0
(the last expression of comma expression) as its type, so this version will match the invoking best.
Otherwise, i.e. operator<<
on T
is not provided, the 2nd version will be adopted.
Upvotes: 1
Reputation: 26040
This can be done using boost.TypeTraits, specifically with has_left_shift. An example:
#include <iostream>
#include "boost/type_traits.hpp"
struct foo
{
int i;
};
struct bar
{
int j;
};
std::ostream& operator<<(std::ostream& os, const foo& f)
{
return os << f.i;
}
int main()
{
// Prints out 1 == true
std::cout << boost::has_left_shift<std::ostream&, foo&, std::ostream&>::value << '\n';
// Prints out 0 == false
std::cout << boost::has_left_shift<std::ostream&, bar&, std::ostream&>::value << '\n';
}
Watch out for the known issues, however, which are listed down the bottom of the documentation.
Upvotes: 5