, Например, если у вас есть функция в безымянном пространстве имен, скажем, подробности реализации, то вы можете использовать декларацию using для ее типа возвращаемого значения или типа параметров. Это вводит имя только в это пространство имен (поэтому на него нельзя ссылаться из других файлов), но, опять же, вас это не должно волновать, поскольку вам не следует включать файл .cc / .cpp (безымянные пространства имен специально предназначены для избежания Конфликты имен во время ссылки, что здесь неприменимо: это просто псевдоним во время компиляции). Хуже того, это вносит двусмысленность, если это имя уже существует!

асно ли (и правильно) в заголовочном файле C ++ использовать объявление using в пространстве имен следующим образом:

#include <boost/numeric/ublas/vector.hpp>
namespace MyNamespace {
    using boost::numeric::ublas::vector;
    vector MyFunc(vector in);
}

То есть "using boost :: numeric :: ublas :: vector" правильно содержится в блоке MyNamespace, или это будет загрязнять пространство имен любого файла, содержащего этот заголовок?

 Matthieu M.30 мая 2011 г., 14:11
для одного символа ... почему бы вам не использоватьtypedef ?
 Matthieu M.30 мая 2011 г., 14:24
Argh! В C ++ 0x у вас есть способы для создания псевдонимов шаблонов ... хотя вам нужно переопределить все аргументы, которые вы хотите использовать, но в противном случае вы застряли, я думаю.
 Brett Ryland30 мая 2011 г., 14:19
@Matthieu: потому чтоboost::numeric::ublas::vector это шаблон. Ранее я использовал стандартный обходной путь "template typedef" (stackoverflow.com/questions/26151/...), но хотел немного упростить вещи.
 CB Bailey30 мая 2011 г., 13:36
Что именно вы подразумеваете под "пространством имен любого файла"? Это "загрязнит"MyNamespace пространство имен в любой единице перевода с момента объявления объявления об использовании и далее.

Ответы на вопрос(5)

но, безусловно, будет загрязнять пространство имен MyNamespace.

как следует из названия, объявление. Все объявления ограничены включающим блоком (7.2), в данном случае это пространство именMyNamespace, Он не будет виден за пределами этого пространства имен.

 Björn Pollex30 мая 2011 г., 13:54
@ Бретт: И если у них естьusing namespace std; у вас есть столкновение имен. Я всегда предпочитаю полностью квалифицированные имена. Вы всегда можете создать короткий псевдоним для пространства имен.
 ltjax30 мая 2011 г., 14:00
«Это не будет видно за пределами этого пространства имен». - хотя это и правильно, но не наоборот: внешние элементы будут видны директиве using, что потенциально изменит смысл вашего и чужого кода.
 Brett Ryland30 мая 2011 г., 13:51
Спасибо, я думаю, это то, что я пытаюсь получить. По сути, я хочу, чтобы все векторы в этом пространстве имен былиboost::numeric::ublas::vectors так, что любой файл .cpp, который включает этот заголовок и используетusing namespace MyNamespace; объявление использует этот вектор вместоstd::vector, Но не иначе.
Решение Вопроса

это небезопасно - оно не загрязнит другое пространство имен, но опасно по другим причинам:

A using директива будет импортировать что угодноэто в настоящее время видно по имени вы указываете в пространство имен, где вы его используете. В то время как вашusing будет виден только пользователямMyNamespaceдругие вещи извне будут видны вашемуusing декларация.

Так как же это опасно при использовании в заголовке? Поскольку он будет импортировать вещи, которые видны в точке объявления, точное поведение будет зависеть от порядка заголовков, которые вы включаете перед объявлением (могут быть разные вещи, видимые изboost::numeric::ublas::vector). Поскольку вы не можете реально контролировать, какие заголовки включены перед вашим заголовком (и при этом вы не должны быть! Заголовки должны быть самодостаточными!), Это может привести к очень странным проблемам, когда ваша функция найдет одну вещь в одном модуле компиляции, а другую - в следующий.

Как правило большого пальца,using декларации должны использоваться толькопосле все включает в .cpp файл. В книге "Стандарты кодирования C ++" Саттера и Александреску также есть пункт, посвященный именно этому вопросу (пункт 59). Вот цитата: «Но вот обычная ловушка: многие думают, что использование деклараций, выпущенных на уровне пространства имен (...), безопасно. Это не так. Они, по крайней мере, столь же опасны, и более тонким и коварным способом».

Даже если маловероятно, что имя выusing больше нигде не существует (как, наверное, здесь), все может быть ужасно: в заголовке все объявления должны бытьот корки до корки Квалифицированный. Это боль, но в противном случае могут случиться странные вещи.

Также смМиграция в пространства имен, Объявления об использовании и псевдонимы пространства имен а такжеИмена пространства имен для примеров и проблемы, описанной в глубине.

 thomthom15 дек. 2013 г., 23:19
Я также искал способы сделать более читаемый синтаксис без особогоstd:: префикс. Я бы очень хотел использоватьusing ::std::vector в моем собственном пространстве имен, прежде чем я определю свои классы, чтобы код легче читался. Я это понимаюusing namespace рискованно, и я могу понять проблему, еслиusing декларация для функций. Но из того, что я понимаю, единственная проблема с типами - это возможность конфликта, если «кто-то другой» должен определить тип с одинаковым именем в моем пространстве имен. Это действительно такая большая проблема, что никто не использует этот шаблон?
 CB Bailey30 мая 2011 г., 14:19
«Точка все еще в силе, хотя.» Возможно, хотя я должен сказать, что я еще не вижу, в чем проблема для типов.
 Brett Ryland30 мая 2011 г., 14:00
Обратите внимание, что я используюusing boost::numeric::ublas::vectorнеusing namespace boost::numeric::ublas как я не хочу импортировать весьboost::numeric::ublas Пространство имен. Кроме того, так как это объявлено внутриnamespace MyNamespace { } блок, вектор не должен быть двусмысленным, только если кто-то написалusing namespace std; using namespace MyNamespace;?
 CB Bailey30 мая 2011 г., 14:10
@ ltjax: Что именно вы имеете в виду, будет неоднозначным? внутриMyNamespace vector введено с помощьюдекларация будет скрывать любой вектор, видимый в глобальном пространстве имен, введенном с помощьюдиректива, Конечно, это намерение?
 Brett Ryland30 мая 2011 г., 15:19
@ ltjax: Итак, в заключение, если бы я использовалusing ::boost::numeric::ublas::vector в блоке пространства имен в моем заголовочном файле это позволит избежать возможных неоднозначностей в моем заголовочном файле? Если кто-то позже звонитusing namespace std; using namespace MyNamespace в файле .cpp это вызовет неоднозначность, но так будетusing namespace std; using namespace boost::numeric::ublas;... так что проблем не так много, да?

нет, используя-объявления в заголовкене нормальнодаже внутри пространства имен по 2 причинам. Кроме того, объявления использования в пространстве имен в не заголовке подвержены ошибкам или бессмысленны (см. Конец). Объявления об использовании в заголовке не подходят, потому что:

Они вводят имя в пространство имен, которое влияетвсе файлы которые включают в себя заголовок.Они вводят только объявления для имени, которое уже видели, что означает, чтоПоведение зависит от порядка включений!

В вашем примере это означает, что:

ВMyNamespace, vector теперь может разрешитьboost::numeric::ublas::vectorдля любых файлов, которые включают этот заголовок: он "загрязняет"MyNamespace Пространство имен.Которыйboost::numeric::ublas::vector объявления импортируются в зависимости от того, какие объявления появляютсядо это объявление об использовании, которое зависит от порядка включенияв файле, который включает этот заголовок, и всеего включает (правильно, порядок объявлений в блоке перевода, после предварительной обработки).

вВаш комментарий от 30 мая '11 в 11:51 вы на самом деле хотите поведение 1, но это не работает из-за проблемы 2. Вы можете получить желаемое поведение, имея отдельный заголовок, который включается после всех остальных (и полностью определяя имя в других заголовках). Однако, это хрупко и поэтому не рекомендуется, предпочтительно быть зарезервированным только при переходе к пространствам имен:

//--- file myheader.hpp ---
#include <boost/numeric/ublas/vector.hpp>
namespace MyNamespace {
    ::boost::numeric::ublas::vector MyFunc(::boost::numeric::ublas::vector in);
}

//--- file myproject_last.hpp ---
namespace MyNamespace {
    using ::boost::numeric::ublas::vector;
}

//--- file myproject.cpp ---
#include "myheader.hpp"
// ...other includes
#include "myproject_last.hpp"

ВидетьПОЛУЧИЛ № 53: Миграция в пространства имен подробности, этот обходной путь и советы: «Пространство имен, использующее объявления, никогда не должно появляться в заголовочных файлах».

Можно избежать проблемы 1, добавив безымянное пространство имен вокруг декларации using (чтобы эти имена не были видны), а затем еще одно за пределами безымянного пространства имен (чтобы сделать желаемое имясам видимый), но это все еще страдает от проблемы 2 и увеличивает заголовок:

//--- file myheader.hpp ---
#include <boost/numeric/ublas/vector.hpp>
namespace MyNamespace {
    namespace {
        using ::boost::numeric::ublas::vector;
        vector MyFunc(vector in);
    }
    using MyFunc; // MyNamespace::(unique)::MyFunc > MyNamespace::MyFunc
}

Из-за этих проблем вы должны использовать декларации использования только в файлах без заголовка (.cc / .cpp): это не влияет на другие файлы, поэтому проблема 1 избегается; и все заголовки были включены, поэтому проблема 2 устранена. В этом случае это вопрос вкуса, помещаете ли вы их в пространство имен или нет, так как они не влияют на другие файлы; безопаснее всегда использовать полностью определенные имена в самом объявлении использования (абсолютное, начиная с::).

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

Объявление использования внутри функции (или структуры, или класса, или вложенного блока):отлично, Это минимизирует область действия и является лишь делом вкуса: использование-объявления близко к использованию (разборчивость выиграна), но теперь они разбросаны по всему файлу (потеря разборчивости).

Объявление об использовании с относительным именем в (именованном) пространстве имен:подверженные ошибки, Это является более кратким и добавляет некоторую ясность (связанные имена, используемые в пространстве имен, к которому они относятся), но потенциально неоднозначно (как и в случае с относительными путями), и его безопаснее избегать:

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

namespace foo {
    // Implicitly ::foo:bar, could be ::bar, or ::other::foo::bar.
    using bar;
}

Объявление об использовании с абсолютным именем в именованном пространстве имен:бессмысленный, Это вводит имя только в пространство имен, но вас это не должно волновать, поскольку вы не должны включать файл .cc / .cpp:

namespace foo {
    using ::bar;
}

Использование-объявление в безымянном пространстве имен:бессмысленно, немного опасно, Например, если у вас есть функция в безымянном пространстве имен, скажем, подробности реализации, то вы можете использовать декларацию using для ее типа возвращаемого значения или типа параметров. Это вводит имя только в это пространство имен (поэтому на него нельзя ссылаться из других файлов), но, опять же, вас это не должно волновать, поскольку вам не следует включать файл .cc / .cpp (безымянные пространства имен специально предназначены для избежания Конфликты имен во время ссылки, что здесь неприменимо: это просто псевдоним во время компиляции). Хуже того, это вносит двусмысленность, если это имя уже существует!

но это загрязнит пространство имен MyNamespace. Таким образом, любой файл, содержащий этот заголовок, будет иметь функции / классы в MyNamespace.

 thomthom15 дек. 2013 г., 10:50
Но OP импортировал только один тип, а не целое пространство имен. Это загрязняет окружающую среду?

Ваш ответ на вопрос