Подтвердить что ты не робот

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

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

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

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

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

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

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

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

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

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

ADD:

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

4b9b3361

Ответ 1

Вы можете достичь этого с помощью объявления using.

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

namespace bar
{
    using foo::print;
}

ИЗМЕНИТЬ

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

Ответ 2

Как насчет объявления 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, которое может быть потенциально добавлено в будущем, не принесет вам никаких сюрпризов.

Ответ 3

С объявлением 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 предназначено для программистов, компилятор их не заботит, поскольку пространства имен компиляторов похожи на префикс для функций/методов/классов.

Ответ 5

Пример

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
    }
}