Как поместить некоторый код в несколько пространств имен, не дублируя этот код?

Предположим, у меня есть метод, определенный в двух разных пространствах имен:

namespace foo
{
void print()
{
//do work...
}
}

namespace bar
{
void print()
{
//do work...
}
}

foo::print() и bar::print() функции абсолютно равны. Мой проект использует многочисленные вызовы этих функций.

Есть ли способ удалить один из print() определения без изменения вызовов этих функций? Я имею в виду что-то вроде следующего (конечно, язык C ++ не позволяет эту конструкцию, это просто пример):

namespace foo, bar  //wrong code!
{
void print()
{
//do work...
}
}

Если нет способа реорганизовать код так, как я хочу, скажите, пожалуйста, вам нравится следующее решение? Будете ли вы рады, если ваш проект содержит такой код? 🙂

namespace foo
{
void print()
{
//do work...
}
}

namespace bar
{
void print()
{
foo::print();
}
}

ДОБАВЛЯТЬ:

Спасибо, ребята, я полностью удовлетворен вашими ответами. Только один момент, я хочу, чтобы вы уточнить: есть ли разница между using ::foo::print а также using foo::print?

17

Решение

Вы можете достичь этого с using декларация.

namespace foo
{
void print()
{
//do work...
}
}

namespace bar
{
using foo::print;
}

РЕДАКТИРОВАТЬ

Что касается разницы между ::foo::print а также foo::print: добавление завершенного имени с помощью :: означает, что вы явно ссылаетесь на имя в глобальном пространстве имен. Это можно использовать для выбора глобального, даже если есть другой элемент с таким же именем, более близкий по объему.

18

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

Как насчет using объявление:

namespace foo
{
void print()
{
// do work ...
}
}

namespace bar
{
using ::foo::print;
}

С помощью ::foo::print вместо foo::print это важный момент. Если бы у вас был другой foo Внутри bar:

namespace foo
{
void print()
{
// 1 ...
}
}

namespace bar
{
namespace foo
{
void print()
{
// 2 ...
}
}

using   foo::print; // refers to 2
using ::foo::print; // refers to 1
}

тогда вы увидите преимущество использования ::, Подводя итог, готовимся :: это безопасный способ гарантировать, что другое вложенное пространство имен foo, который может быть добавлен в будущем, не принесет вам никаких сюрпризов.

14

С using объявление:

namespace bar
{
using ::foo::print;
}
4

Наверное, лучшее решение это:

namespace foo
{
void print()
{
//do work...
}
}

namespace bar
{
void print()
{
foo::print();
}
}

Однако вы можете написать:

namespace foo
{
void print()
{
//do work...
}
}

namespace bar
{
void print()
{
//do work...
}
}

Это не рекомендуется, но зла нет. Компиляторы достаточно умны, чтобы понять, что эти две функции одинаковы и могут использовать один и тот же код сборки.

Помните, namespace Ключевое слово предназначено для программистов, компилятор не заботится о них, потому что пространства имен компилятора подобны префиксу для функций / методов / классов.

0

Образец

namespace Q {
namespace V {
void f(); // enclosing namespaces are the global namespace, Q, and Q::V
class C { void m(); };
}
void V::f() { // enclosing namespaces are the global namespace, Q, and Q::V
extern void h(); // ... so this declares Q::V::h
}
void V::C::m() { // enclosing namespaces are the global namespace, Q, and Q::V
}
}
-2
По вопросам рекламы [email protected]