2010-02-10 81 views
9

为了测试并显示我的函数库的一些函数的结果,我创建了一组方便的函数。重载全局类型转换运算符

我有一个execute功能,看起来像:

template <typename R, typename I> 
std::string execute(const std::string& func_name, R(*func_ptr)(const I&), const I& func_input); 

它调用的函数,并显示在一个格式化字符串,我可以向std::cout结果和参数。

问题是,我的一些功能不返回可转换为字符串结果。我以为我可以简单的东西,如超载全球::operator std::string

template <typename T> 
operator std::string(const std::vector<T>& v); 

但是GCC抱怨:

error: 'operator std::string(const std::vector<T, std::allocator<_CharT> >&)' must be a nonstatic member function 

嘛,当然问题是,我不能成员运营商加入到std::vector,连服我的班级,我不想污染他们“测试”转换运营商。

我想我可以添加一个间接层并使用函数而不是转换操作符,但那不是更美观的解决方案。我也可以为std::ostream重载::operator <<并使用std::ostringstream,但这也不是最干净的解决方案。

我想知道全局转换运算符是否真的不可重载,如果有,为什么。

回答

10

转换运算符(演员操作符)必须是生成转换类型的转换类的成员。作为赋值运算符,它们必须是成员函数,正如编译器告诉你的那样。

根据您想要在调试部分投入多少努力,您可以尝试使用元编程将您的执行方法转发给不同的实际实现,为将打印内容的容器提供特定的实现方法。

为什么你不想为你的类型提供operator<<?我认为这实际上是一种惯用的解决方案。不像您使用转换为字符串产生打印结果的方法,在C++中惯用的方式与其他语言中提供operator<<,然后使用stringstreams(或boost::lexical_cast或一些类似的解决方案)转换为基于该operator<<执行字符串。有一个简单的工具类here从,如果你想使用一个起点重写operator<<元素创建string

1

没有用户定义的全局转换运算符。您必须控制目标类型(在这种情况下,非显式的一个参数构造函数是转换运算符)或源类型(在这种情况下,您必须重载成员运算符target())。

4

我想知道全局转换运算符是否真的不可重载,如果有,为什么。

不,没有这样的事情。转换函数必须是类的成员。如果不是这样,那么通过引入含糊不清,它会使重载问题成为编译器特别棘手的问题。

+1

但是许多运营商都可以作为全局或成员,何乐不为呢?例如,如果有一个全局和成员操作符<<,编译器会抱怨模糊的调用,它可能会对convertions做同样的事情。 – NewbiZ 2010-02-10 08:12:38

+2

转换函数是特殊的成员函数(因为是构造函数,析构函数,OP =和拷贝构造),因为它们参与转化/对象创建。见12.3。 – dirkgently 2010-02-10 08:17:23

0

转换函数必须是成员函数。该函数可能不指定返回类型,并且参数列表必须为空。应该谨慎地使用它们,并且应该有从一种类型到另一种类型的明确转换路径。否则,他们可能会导致意想不到的结果和神秘的错误。

0

不幸的是,没有这样的事,作为一个全球性的铸造操作。出奇。但模板是你的朋友。

有时候你不想暴露铸造界面看跌希望保持这种匿名的只是一个具体的实施。我通常会添加一个模板()方法,它也可以做中投类型检查等,让您处理您要实现铸造(例如动态共享,文献等)的方法的类。

事情是这样的:

template< class EvtT >const EvtT& as() const throw(std::exception) 
    { 
     const EvtT* userData = static_cast<const EvtT*>(m_UserData); 
     ASSERT(userData, "Fatal error! No platform specific user data in input event!"); 
     return *userData; 
    } 

m_UserData是只有实现知道匿名类型。虽然这是严格的非类型转换(我在这里不使用类型转换),但这可以由dynamic_cast和适当的转换异常来替代。

的执行简单地做到这一点:

unsigned char GetRawKey(const InputEvent& ie) 
    { 
     const UserEvent& ue = ie.as<const UserEvent>(); 
     ...