简体   繁体   English

重载全局类型转换运算符

[英]Overloading the global type conversion operator

To test and display the result of some functions of my library, I am creating a set of handy functions. 为了测试和显示我的库的某些功能的结果,我正在创建一组方便的功能。

I have an execute function that looks like : 我有一个execute函数,看起来像:

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

It calls the function, and display the results and arguments in a formatted string that I can send to std::cout . 它调用该函数,并在格式化的字符串中显示结果和参数,我可以将其发送到std::cout

The problem is that some of my functions do not return convertible-to-string results. 问题是我的一些函数没有返回convertible-to-string结果。 I thought I could simply overload the global ::operator std::string with something like: 我以为我可以简单地重载global ::operator std::string ,例如:

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

But GCC complains: 但海湾合作委员会抱怨说:

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

Well, the problem of course is that I cannot add member operators to std::vector , and even for my classes, I don't want to pollute them with "for testing" conversion operators. 好吧,问题当然是我不能将成员运算符添加到std::vector ,甚至对于我的类,我也不想用“for testing”转换运算符来污染它们。

I guess that I can add a layer of indirection and use a function instead of a conversion operator, but that would not be the more aesthetic solution. 我想我可以添加一个间接层并使用函数而不是转换运算符,但这不是更美观的解决方案。 I could also overload ::operator << for std::ostream and use a std::ostringstream , but that also is not the cleanest solution. 我也可以重载::operator << for std::ostream并使用std::ostringstream ,但这也不是最干净的解决方案。

I wondered if the global conversion operator is really not overloadable, and if so, why. 我想知道全局转换运算符是否真的不能超载,如果是,为什么呢。

Conversion operators (cast operators) must be a member of the convertible class that produces the converted type. 转换运算符(强制转换运算符)必须是生成转换类型的可转换类的成员。 As assignment operators, they must be member functions, as your compiler is telling you. 作为赋值运算符,它们必须是成员函数,正如编译器告诉您的那样。

Depending on how much effort you want to put into the debug part of it, you could try to use metaprogramming to forward your execute method to different actual implementations, providing specific ones for containers that will print the contents. 根据您希望将多少工作量放入调试部分,您可以尝试使用元编程将执行方法转发到不同的实际实现,为将打印内容的容器提供特定的实现方法。

Why don´t you want to provide operator<< for your types? 为什么你不想为你的类型提供operator<< I think that is actually the idiomatic solution. 我认为这实际上是惯用的解决方案。 Unlike other languages that you use methods that convert to string to produce printable results, in C++ the idiomatic way is providing operator<< and then using stringstreams (or boost::lexical_cast or some similar solution) to convert to strings based on the operator<< implementation. 与使用转换为字符串以产生可打印结果的方法的其他语言不同,在C ++中,惯用方法是提供operator<<然后使用stringstreams (或boost::lexical_cast或类似的解决方案)来转换为基于operator<<字符串operator<<实施。 There is a simple utility class here to create a string from elements that override operator<< if you want to use that for a start point. 这里有一个简单的实用程序类用于从覆盖operator<<元素创建一个string ,如果你想将它用作起点。

I wondered if the global conversion operator is really not overloadable, and if so, why. 我想知道全局转换运算符是否真的不能超载,如果是,为什么呢。

No, there is no such thing. 不,没有这样的事情。 Conversion functions must be a member of a class. 转换函数必须是类的成员。 If it weren't so, it would make overload resolution a particularly vexing problem for the compiler by introducing ambiguities. 如果不是这样,那么通过引入歧义会使重载决策成为编译器特别棘手的问题。

There is no user defined global conversion operator. 没有用户定义的全局转换运算符。 You must control either the target type (in which case a non explicit one parameter constructor is the conversion operator) or the source type (in which case you have to overload the member operator target()). 您必须控制目标类型(在这种情况下,非显式的一个参数构造函数是转换运算符)或源类型(在这种情况下,您必须重载成员运算符target())。

Unfortunately there is no such thing as a global casting operator. 不幸的是,没有全球铸造运营商这样的东西。 Surprisingly. 出奇。 But templates are your friend. 但模板是你的朋友。

Sometimes you do not want to expose the casting to the interface put would want to keep this anonymous for a specific implementation only. 有时您不希望将转换暴露给接口,而是希望仅针对特定实现保持匿名。 I usually add a template as() method to the class which can also do type checks in the cast, etc. and lets you handle the way you want to implement the casting (eg dynamic, shared, ref, etc). 我通常在类中添加一个模板as()方法,它也可以在强制转换等中进行类型检查,并让你处理你想要实现强制转换的方式(例如dynamic,shared,ref等)。

Something like this: 像这样的东西:

    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 is an anonymous type which only the implementation knows. m_UserData是一个匿名类型,只有实现知道。 While this is strictly a non-typed cast (I do not use type cecks here) this could be replaced by a dynamic_cast and proper casting exceptions. 虽然这是严格的非类型转换(我不在这里使用类型cecks),但可以用dynamic_cast和正确的转换异常代替。

The implementation simply does this: 实现只是这样做:

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

A conversion function must be a member function. 转换函数必须是成员函数。 The function may not specify a return type, and the parameter list must be empty. 该函数可能未指定返回类型,参数列表必须为空。 They should be used sparingly and there should be a clear conversion path from one type to another type. 它们应该谨慎使用,并且应该有一种从一种类型到另一种类型的明确转换路径。 Otherwise they can lead to unexpected results and mysterious errors. 否则他们可能会导致意想不到的结果和神秘的错误。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM