C ++:不同命名空间中的多个运算符定义

时间:2015-11-26 09:22:02

标签: c++ namespaces operator-overloading shadowing

我对operator<<的两个定义之间的冲突感到不安。

假设我一直是ACE库的忠实粉丝并且在我的代码中使用ACE_Time_Value。有一天,我注意到ACE 6.x已经出局,并试图将我的代码从ACE 5.x迁移到6.x.然后我遇到了一个问题:ACE 6.x在全局命名空间中新引入了operator<<(std::ostream &, const ACE_Time_Value &),但是我的代码自5.x时代开始实现了我自己的operator<<版本,并且两个operator<<冲突了。不幸的是,“官方”operator<<的输出不能令人满意,我需要继续使用我自己的版本。我怎么能假装全局命名空间中没有“官方”operator<<?幸运的是(?)我的所有代码都在我自己的命名空间内。

从概念上讲,我的问题可归纳为:

#include <iostream>
using namespace std;

struct ACE_Time_Value { };
ostream &operator<<(ostream &os, const ACE_Time_Value &) { os << "Apple" ; }
void foo(const ACE_Time_Value &) { cout << "Cherry" << endl; }

namespace mine {
    ostream &operator<<(ostream &os, const ACE_Time_Value &) { os << "Banana" ; }
    void foo(const ACE_Time_Value &) { cout << "Durian" << endl; }

    void bar() {
        ACE_Time_Value t;
        ::mine::foo(t); // OK
        // cout << "The current time is " <<
        //   t << endl; // error: ambiguous overload for 'operator<<'
    }
}

int main() {
    mine::bar();
}

4 个答案:

答案 0 :(得分:1)

您可以执行以下操作并使用继承:

#include <iostream>
using namespace std;

struct ACE_Time_Value { };
ostream &operator<<(ostream &os, const ACE_Time_Value &) { os << "Apple" ; return os; }
void foo(const ACE_Time_Value &) { cout << "Cherry" << endl; }

namespace mine {
        struct New_ACE_Time_Value: ACE_Time_Value {};

        ostream &operator<<(ostream &os, const New_ACE_Time_Value &) { os << "Banana" ;
            return os;
        }
        void foo(const ACE_Time_Value &) { cout << "Durian" << endl; }

        void bar() {
                New_ACE_Time_Value t;
                ::mine::foo(t); // OK
                cout << "The current time is " <<
                   t << endl; // error: ambiguous overload for 'operator<<'
        }
}

可能你也应该让'NewACE_Time_Value'不可复制,以摆脱对象切片问题。

答案 1 :(得分:0)

这就是我如何解决你的概念性例子:

#include <iostream>
using namespace std;

struct ACE_Time_Value { };

namespace ACE
{
    ostream &operator<<(ostream &os, const ACE_Time_Value &) { os << "Apple" ; return os; }
}

void foo(const ACE_Time_Value &) { cout << "Cherry" << endl; }

namespace mine {
    ostream &operator<<(ostream &os, const ACE_Time_Value &) { os << "Banana" ; return os; }
    void foo(const ACE_Time_Value &) { cout << "Durian" << endl; }

    void bar() {
        ACE_Time_Value t;
        ::mine::foo(t); // OK
        cout << "The current time is " << t << endl;
    }
}

int main() {
    mine::bar();
}

由于ACE是开源的,因此应用相同的修改以使其<<operator重载包含在命名空间内并不太难。

答案 2 :(得分:0)

首先,您应该添加&#34;返回操作系统;&#34;在我们的运算符重载(&lt;&lt;&lt;)中。 其次,将预处理程序指令添加到两个中的一个&lt;&lt;像这样重载:

#ifdef Oper
ostream &operator<<(ostream &os, const ACE_Time_Value &) 
{
  os << "Banana"    ; return os; 
}
#endif

答案 3 :(得分:0)

我最终定义了一个包含operator<<的包装器对象。

namespace mine {
    void foo(const ACE_Time_Value &) { cout << "Durian" << endl; }
    struct AceTimePrinter {
        const ACE_Time_Value &tv;
        AceTimePrinter(const ACE_Time_Value &tv) : tv(tv) { }
        inline friend std::ostream &operator<<(
                std::ostream &os, const AceTimePrinter &o) {
            const ACE_Time_Value &tv = o.tv;
            return os << "Durian" ;
        }
    };

    void bar() {
        ACE_Time_Value t;
        ::mine::foo(t); // OK
        cout << "The current time is " <<
            AceTimePrinter(t) << endl;
    }
}

我们选择不使用继承,因为我们无法更改ACE reactor框架中的现有方法签名,例如virtual int handle_timeout (const ACE_Time_Value &current_time, const void *act=0)