2017-10-21 39 views
3

我有这样的代码C++ - 汽车铸件的std :: string

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

,并在主

T2 tx; 
tx.x = "hellow";  
tx.y = 10; 

std::cout << static_cast<std::string>(tx.x) << ::std::endl; 
std::cout << tx.y << ::std::endl; 

这是正常工作。但是,这样做只是这

std::cout << tx.x << ::std::endl; 

将在

错误C2679结束:二进制“< <”:没有操作员发现这需要类型的右手操作数‘测试:: KeyValueProperty’(或 没有可接受的转换)

是否有可能进行自动转换,或者我必须手动调用铸造?

回答

2

t.y即使工作没有定制operator<<是因为已经存在的operator<<(std::ostream&, double)的原因,编译器也可以看到它可以让你的班级脱离double。它这样做,我们很高兴。

但是,没有operator<<(std::ostream&, std::string)。如果有的话,同样的逻辑将适用,我们仍然会很高兴。取而代之的是:

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

也就是说,对于任何形式的basic_string通用插入运算符。

尽管存在一些模板参数会使它看起来好像是operator<<(std::ostream&, std::string),但编译器不会尝试猜测哪些可能的模板参数会允许它随后将您的类转换为结果。组合太多,所以这是不允许的。

这就是为什么你必须明确地把你的对象转化为std::string(又名std::basic_string<char>) - 这将删除问题的一个层,它可以做普通的旧型扣,使这项工作。

正确的解决方案是给你的包装类一个插入操作符来回避这个问题。

1

您必须提供运营商< <适当超载,例如:

template<class T> 
std::ostream& operator<<(std::ostream& os, KeyValueProperty<T> const& kvp) 
{ 
    return os << T(kvp); 
} 
+1

但是,即使没有这个,为什么双重输出呢? –

+0

@MartinPerry KeyValueProperty对T&隐式转换运算符。 –

+1

但是,为什么这个隐式转换对于std :: string不起作用,如果它是用于double的呢? –