I want to test whether a class is streamable to ostream&
by seeing whether an overload for operator<<
is provided. Based on these posts, I tried to write another version using C++11. This is my attempt:
#include <iostream>
#include <type_traits>
namespace TEST{
class NotDefined{};
template<typename T>
NotDefined& operator << (::std::ostream&, const T&);
template <typename T>
struct StreamInsertionExists {
static std::ostream &s;
static T const &t;
enum { value = std::is_same<decltype(s << t), NotDefined>() };
};
}
struct A{
int val;
friend ::std::ostream& operator<<(::std::ostream&, const A&);
};
::std::ostream& operator<<(::std::ostream& os, const A& a)
{
os << a.val;
return os;
}
struct B{};
int main() {
std::cout << TEST::StreamInsertionExists<A>::value << std::endl;
std::cout << TEST::StreamInsertionExists<B>::value << std::endl;
}
But this fails to compile:
test_oper.cpp:40:57: error: reference to overloaded function could not be resolved; did you mean to call it? std::cout << TEST::StreamInsertionExists<A>::value << std::endl; /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/ostream:1020:1: note: possible target for call endl(basic_ostream<_CharT, _Traits>& __os) test_oper.cpp:30:17: note: candidate function not viable: no known conversion from 'TEST::NotDefined' to '::std::ostream &' (aka 'basic_ostream<char> &') for 1st argument ::std::ostream& operator<<(::std::ostream& os, const A& a) test_oper.cpp:15:15: note: candidate template ignored: couldn't infer template argument 'T' NotDefined& operator << (::std::ostream&, const T&);
However, if I replace the line
enum { value = std::is_same<decltype(s << t), NotDefined>() };
with
static const bool value = std::is_same<decltype(s << t), NotDefined>();
then everything compiles.
Why is there such a difference between the enum
and the bool
?