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

C++: multiple operator definitions in different namespaces

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

假设我一直是 ACE 库的忠实粉丝并且一直在我的代码中使用 ACE_Time_Value。有一天,我注意到 ACE 6.x 出局了,并试图将我的代码从 ACE 5.x 迁移到 6.x。然后我遇到了一个问题:ACE 6.x new introduced operator<<(std::ostream &, const ACE_Time_Value &) in the global namespace,但是我的代码从5.x时代开始实现了我自己版本的operator<<,两个operator<< 冲突。不幸的是 "official" operator<< 的输出并不令人满意,我需要继续使用我自己的版本。我如何假装全局命名空间中没有 "official" 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();
}

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

#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' 不可复制以摆脱对象切片问题。

这就是我将如何解决您的概念性示例:

#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 重载被包装在命名空间中。

首先,您应该在我们的运算符重载 (<<) 中添加 "return os;"。 其次,将预处理器指令添加到两个 << 重载之一,如下所示:

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

我最终用 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 反应器框架中现有的方法签名,例如 virtual int handle_timeout (const ACE_Time_Value &current_time, const void *act=0)