Reputation: 9527
I have this code
template <typename T>
class KeyValueProperty {
protected:
T value = T();
std::string key = "";
public:
KeyValueProperty(const std::string & key) : key(key) { }
T & operator = (const T &i) { return value = i; };
operator const T & (){ return value; };
};
struct T2 {
KeyValueProperty<std::string> x {"x"};
KeyValueProperty<double> y {"y"};
};
and in main
T2 tx;
tx.x = "hellow";
tx.y = 10;
std::cout << static_cast<std::string>(tx.x) << ::std::endl;
std::cout << tx.y << ::std::endl;
This is working correctly. However, doing only this
std::cout << tx.x << ::std::endl;
will end up in
error C2679: binary '<<': no operator found which takes a right-hand operand of type 'Test::KeyValueProperty' (or there is no acceptable conversion)
Is it possible to have auto-conversion, or I must manually call casting?
Upvotes: 3
Views: 5432
Reputation: 503913
The reason t.y
works even without a custom operator<<
is because there already exists an operator<<(std::ostream&, double)
, and the compiler can also see that it can make a double
out of your class. It does so and we're happy.
However, there is no operator<<(std::ostream&, std::string)
. If there was, the same logic would apply and we'd still be happy. Instead, there is:
template <class CharT, class Traits, class Allocator>
std::basic_ostream<CharT, Traits>&
operator<<(std::basic_ostream<CharT, Traits>& os,
const std::basic_string<CharT, Traits, Allocator>& str);
That is, a generic insertion operator for any kind of basic_string
.
Although there exist some template arguments that would make this as if it were operator<<(std::ostream&, std::string)
, the compiler isn't going to try and guess which possible template arguments would allow it to subsequently match a conversion of your class to the result. There are too many combinations, so this isn't permitted.
This is why you had to explicitly turn your object into a std::string
(aka std::basic_string<char>
) - this removes one layer from the problem and it can do regular old type deduction to make this work.
The right solution is to give your wrapper class an insertion operator, to sidestep this issue.
Upvotes: 2
Reputation: 69892
You must provide an appropriate overload of operator<<, for example:
template<class T>
std::ostream& operator<<(std::ostream& os, KeyValueProperty<T> const& kvp)
{
return os << T(kvp);
}
Upvotes: 1