Вопрос: можно ли получить доступ к определенному классу из заголовка, скрывая при этом другие пространства имен / классы, определенные в этом заголовке?
Например, скажем, у меня есть файл заголовка - result.hpp:
// outcome.hpp
namespace sports { namespace outcome {
class Injury {};
class Success {};
}}
В другом файле заголовка - api.hpp - я хочу использовать sports::outcome::Injury без доступа sports::outcome::Success к файлам, которые включают api.hpp. Это возможно? Если да, то как я могу этого добиться?
P.S. В реальном коде api.hpp содержит шаблонные методы, которые будут вызывать методы класса Injury, поэтому прямого объявления недостаточно.
Мои попытки:
По своему незнанию я попытался добиться этого, поместив include во внутреннее пространство имен. Вот SSCCE:
// api.hpp
namespace sports { namespace api {
namespace internal {
#include "outcome.hpp" // I'm trying to hide symbols within this header
using sports::outcome::Injury;
}
class Boxing {
private:
internal::Injury sustained;
};
}
Я преждевременно праздновал, когда это сработало:
// This cpp file compiles file \o/
#include "api.hpp"
int main(int argc, char *argv[]) {
sports::api::Boxing b;
// sports::outcome not accessible
}
Как это не удается:
Все развалится, если контейнер из стандартной библиотеки используется в качестве члена класса в result.hpp. Например, используя эту версию:
// outcome.hpp
#include <vector>
namespace sports { namespace outcome {
class Injury {
private:
std::vector x;
};
// ...
}}
Компиляция завершается ошибкой из-за следующих ошибок:
In file included from /usr/include/c++/4.6/ext/new_allocator.h:34:0,
from /usr/include/c++/4.6/x86_64-linux-gnu/./bits/c++allocator.h:34,
from /usr/include/c++/4.6/bits/allocator.h:48,
from /usr/include/c++/4.6/vector:62,
from outcome.hpp:1,
from api.hpp:5,
from main.cpp:1:
/usr/include/c++/4.6/new:93:54: error: ‘void* sports::api::internal::operator new(sports::api::internal::std::size_t)’ may not be declared within a namespace
/usr/include/c++/4.6/new:94:56: error: ‘void* sports::api::internal::operator new [](sports::api::internal::std::size_t)’ may not be declared within a namespace
/usr/include/c++/4.6/new:95:35: error: ‘void sports::api::internal::operator delete(void*)’ may not be declared within a namespace
/usr/include/c++/4.6/new:96:37: error: ‘void sports::api::internal::operator delete [](void*)’ may not be declared within a namespace
/usr/include/c++/4.6/new:97:62: error: ‘void* sports::api::internal::operator new(sports::api::internal::std::size_t, const sports::api::internal::std::nothrow_t&)’ may not be declared within a namespace
/usr/include/c++/4.6/new:98:64: error: ‘void* sports::api::internal::operator new [](sports::api::internal::std::size_t, const sports::api::internal::std::nothrow_t&)’ may not be declared within a namespace
/usr/include/c++/4.6/new:99:58: error: ‘void sports::api::internal::operator delete(void*, const sports::api::internal::std::nothrow_t&)’ may not be declared within a namespace
/usr/include/c++/4.6/new:100:60: error: ‘void sports::api::internal::operator delete [](void*, const sports::api::internal::std::nothrow_t&)’ may not be declared within a namespace
/usr/include/c++/4.6/new:103:57: error: ‘void* sports::api::internal::operator new(sports::api::internal::std::size_t, void*)’ may not be declared within a namespace
/usr/include/c++/4.6/new:104:59: error: ‘void* sports::api::internal::operator new [](sports::api::internal::std::size_t, void*)’ may not be declared within a namespace
/usr/include/c++/4.6/new:107:52: error: ‘void sports::api::internal::operator delete(void*, void*)’ may not be declared within a namespace
/usr/include/c++/4.6/new:108:52: error: ‘void sports::api::internal::operator delete [](void*, void*)’ may not be declared within a namespace
Я явно делаю это неправильно. Мы будем очень благодарны за совет и хорошее выступление.
sports::outcome::*был доступен в файлах, содержащих api.hpp. - person Shawn Chin   schedule 14.11.2012