Подводя итог, нет , объявления использования в заголовке не в порядке , даже в пространстве имен, по 2 причинам.Кроме того, объявления использования в пространстве имен в не заголовке подвержены ошибкам или бессмысленны (см. Конец).Объявления использования в заголовке не подходят, потому что:
- Они вводят имя в пространство имен, что влияет на все файлы , которые включают заголовок.
- Онивводите только объявления для имени, которое уже было замечено, что означает, что поведение зависит от порядка включений!
В вашем примере это означает, что:
- В пределах
MyNamespace
, vector
теперь может преобразовываться в boost::numeric::ublas::vector
для любых файлов, которые содержат этот заголовок: он «загрязняет» пространство имен MyNamespace
. - Какие
boost::numeric::ublas::vector
объявления являютсяИмпорт зависит от того, какие объявления появляются перед этим объявлением использования, что зависит от порядка включения в файл, который включает этот заголовок, и все его включает (правильно, порядок объявлений в модуле перевода, после предварительной обработки).
За ваш комментарий от 30 мая '11 в 11: 51 вы на самом деле хотите поведение 1, ноэто не работает, из-за проблемlem 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 (безымянные пространства имен специально предназначены для избежания Конфликты имен во время ссылки, что здесь неприменимо: это просто псевдоним во время компиляции). Хуже того, это вносит двусмысленность, если это имя уже существует!