try something like this
template<typename T, typename V = bool>
struct is_objc_class : std::false_type { };
template<typename T>
struct is_objc_class<T,
typename std::enable_if<std::is_convertible<T, id>::value, bool>::type
> : std::true_type { };
template <
class T,
class = typename std::enable_if<is_objc_class<T>::value>::type
>
std::ostream& operator<< (std::ostream& stream, T const & t) {
stream << [[t description] UTF8String];
return stream;
}
struct Logger
{
Logger(std::ostream &s):stream(s){}
std::ostream &stream;
// for objc class
template <class T>
typename std::enable_if<is_objc_class<T>::value, Logger&>::type
operator<< (T const & t) {
stream << [[t description] UTF8String];
return *this;
}
// for everything else
template <class T>
typename std::enable_if<!is_objc_class<T>::value, Logger &>::type
operator<< (T const & t) {
stream << t;
return *this;
}
};
int main(int argc, char *argv[])
{
std::cout << std::boolalpha
<< is_objc_class<id>::value << std::endl
<< is_objc_class<int>::value << std::endl
<< is_objc_class<NSString *>::value << std::endl
<< @"test" << std::endl
<< @[@1] << std::endl
;
Logger l(std::cout);
l << @"test" << "test2" << @1 << 1;
}