Подводя итог, нет, объявления-использования в заголовке недопустимы даже в пределах пространства имен по двум причинам. Кроме того, объявления using в пространстве имен без заголовка подвержены ошибкам или бессмысленны (см. Конец). Использование-объявлений в заголовке недопустимо, потому что:
- Они вводят имя в пространство имен, которое влияет на все файлы, содержащие заголовок.
- Они вводят только объявления для имени, которое уже было просмотрено, что означает, что поведение зависит от порядка включения!
В вашем примере это означает, что:
- Внутри
MyNamespace
, vector
теперь может разрешиться в boost::numeric::ublas::vector
для любых файлов, которые включают этот заголовок: он "загрязняет" пространство имен MyNamespace
.
- Какие
boost::numeric::ublas::vector
объявления импортируются, зависит от того, какие объявления появляются перед этим объявлением-использованием, что зависит от порядка включения в файл, который включает этот заголовок, и всех его strong> includes (правильно, порядок объявлений в блоке перевода после предварительной обработки).
За ваш комментарий от 30 мая 2011 г. в 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"
См. GotW # 53: Миграция в пространства имен для получения дополнительных сведений, этого обходного пути и советов: " Пространства имен, использующие объявления, никогда не должны появляться в файлах заголовков ".
Можно избежать проблемы 1, добавив безымянное пространство имен вокруг объявления-использования (чтобы эти имена не были видимыми), а затем еще одно за пределами безымянного пространства имен (чтобы сделать желаемое имя само видимым) , но это по-прежнему страдает от проблемы 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
}
Из-за этих проблем вам следует использовать объявления using только в файлах без заголовков (.cc / .cpp): это не влияет на другие файлы, поэтому проблемы 1 можно избежать; и все заголовки включены, поэтому проблема 2 устранена. В этом случае - дело вкуса, помещаете ли вы их в пространство имен или нет, поскольку они не влияют на другие файлы; безопаснее всего всегда использовать полностью определенные имена в самом объявлении using (абсолютное, начиная с ::
).
Самый простой - разместить все объявления-использования в верхней части файла после включений, но вне каких-либо пространств имен: это безопасно, однозначно, легко читается и позволяет использовать имена во всем файле. Некоторые общие отклонения:
- Объявление-использования внутри функции (или структуры, или класса, или вложенного блока): отлично. Это минимизирует область видимости и является лишь вопросом вкуса: объявление-использования близко к использованию (выигрыш в удобочитаемости), но теперь они разбросаны по всему файлу (потеря читаемости).
Объявление-использования с относительным именем в (именованном) пространстве имен: подвержено ошибкам. Это более лаконично и добавляет некоторую ясность (связанные имена, используемые в пространстве имен, к которому они относятся), но потенциально неоднозначно (точно так же, как включает в себя с относительными путями), и его безопаснее избегать:
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 (безымянные пространства имен специально предназначены для избежания конфликты имен во время компоновки, что здесь неприменимо: это просто псевдоним времени компиляции). Хуже того, это вводит двусмысленность, если это имя уже существует!
person
Nils von Barth
schedule
22.05.2016
MyNamespace
в любой единице перевода, начиная с момента объявления объявления using и далее. - person CB Bailey   schedule 30.05.2011typedef
? - person Matthieu M.   schedule 30.05.2011boost::numeric::ublas::vector
- это шаблон. Раньше я использовал стандартный обходной путь typedef шаблона (stackoverflow.com/questions/26151/), но хотел немного упростить. - person Brett Ryland   schedule 30.05.2011