C ++ ambiguous overload for generic ostream template << operator

This question follows my previous question: Generic <<ostream C ++ operator for a stringifiable class , where I would like to implement a generic <<ostreamoperator that will work for any class to which the method belongs to_str().

I was able to check whether the class implements the method to_str()and uses answer instd::cout << stringify(a) this way . However, it’s hard for me to write templates to create .ostream<<std::cout << a

The following test code:

#include <iostream>
#include <sstream>
#include <string>

template<class ...> using void_t = void;

template<typename T, typename = void>
struct has_to_string
: std::false_type { };

template<typename T>
struct has_to_string<T, 
    void_t<decltype(std::declval<T>().to_str())>
    >
: std::true_type { };

template<typename T> std::enable_if_t<has_to_string<T>::value, std::string> 
stringify(T t) { 
    return t.to_str(); 
} 

template<typename T> std::enable_if_t<!has_to_string<T>::value, std::string> 
stringify(T t) { 
    return static_cast<std::ostringstream&>(std::ostringstream() << t).str(); 
} 

// The following does not work
/*
template<typename T> std::enable_if_t<has_to_string<T>::value, std::ostream&> 
operator<<(std::ostream& os, const T& t) {
    os << t.to_str();
    return os;
}

template<typename T> std::enable_if_t<!has_to_string<T>::value, std::ostream&> 
operator<<(std::ostream& os, const T& t) {
    os << t;
    return os;
}
*/

struct A {
    int a;
    std::string to_str() const { return std::to_string(a); }
};

struct B {
    std::string b;
    std::string to_str() const { return b; }
};

int main() {
    A a{3};
    B b{"hello"};
    std::cout << stringify(a) << stringify(b) << std::endl;    // This works but I don't want to use stringify
    // std::cout << a << b << std::endl;               // I want this but it does not work
}

gives the same error as in the original question. What am I doing wrong?

+4
1

'operator < < , std::string, , ostream.

, , :

int main() {
    std::cout << std::string("There is your problem") << std::endl;
}

.

, < < .

std::ostream& operator<<(std::ostream& os, const std::string& t) {
    using std::operator<<;
    os << t;
    return os;
}
+2

All Articles