【问题标题】:C++: multiple operator definitions in different namespacesC++:不同命名空间中的多个运算符定义
【发布时间】:2015-11-26 09:22:01
【问题描述】:

我对@9​​87654323@ 的两个定义之间的冲突感到困扰。

假设我一直是 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();
}

【问题讨论】:

  • 这是一个可怕的问题,我找不到任何好的解决方案。一些丑陋的变通方法可能是将ostreams 包装到一个helper 类 My_ostream 中,并提供一个operator&lt;&lt;,它与std::ostream 的所有类型的版本相同,但ACE_Time_Value 除外,然后使用那些包装的流而不是标准的。
  • 从供应商标题中注释掉错误的operator&lt;&lt; 可能是最好的解决方案

标签: c++ namespaces operator-overloading shadowing


【解决方案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”不可复制以摆脱对象切片问题。

【讨论】:

    【解决方案2】:

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

    #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 是开源的,因此应用相同的修改应该不会太难,以便将它们的 &lt;&lt;operator 重载包装在命名空间中。

    【讨论】:

      【解决方案3】:

      首先,您应该添加“return os;”在我们的运算符重载(

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

      【讨论】:

        【解决方案4】:

        我最终用operator&lt;&lt; 定义了一个包装器对象。

        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 &amp;current_time, const void *act=0)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-10-04
          • 1970-01-01
          • 2015-04-26
          • 2010-09-15
          • 1970-01-01
          • 2012-08-22
          • 1970-01-01
          相关资源
          最近更新 更多