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 ¤t_time, const void *act=0)
我对 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 ¤t_time, const void *act=0)