3

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?

0

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

Comments

1

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); } 

4 Comments

But why is double outputed even without this?
@MartinPerry KeyValueProperty has an implicit conversion operator to T&.
But why is this implicit conversion not working for std::string if it is working for double?
@MartinPerry another answer has appeared which explains this. stackoverflow.com/a/46861259/2015579

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.