C ++: определения нескольких операторов в разных пространствах имен

Я обеспокоен конфликтом между двумя определениями operator<<,

Предположим, что я большой поклонник библиотеки ACE и использую ACE_Time_Value в моем коде. Однажды я заметил, что ACE 6.x вышел, и попытался перенести мой код из ACE 5.x в 6.x. Тогда у меня возникла проблема: ACE 6.x недавно представлен operator<<(std::ostream &, const ACE_Time_Value &) в глобальном пространстве имен, но мой код реализовал мою собственную версию operator<< с эпохи 5.х и два 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();
}

3

Решение

Вы можете сделать что-то вроде ниже и использовать наследование:

#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

Другие решения

Вот как бы я решил ваш концептуальный пример:

#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 Перегрузка заключена в пространство имен.

0

Во-первых, вы должны добавить «return os;» у нашего оператора перегрузка (<<).
Во-вторых, добавьте директивы препроцессора к одному из двух << перегрузка вот так:

#ifdef Oper
ostream &operator<<(ostream &os, const ACE_Time_Value &)
{
os << "Banana"    ; return os;
}
#endif
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, такие как virtual int handle_timeout (const ACE_Time_Value &current_time, const void *act=0)

0
По вопросам рекламы [email protected]