我有一个命名空间N0
,它有子命名空间,包括N1
。调用代码只知道外部命名空间。我想在外部命名空间中编写一个函数,该函数返回std::unique_ptr<N1::T>
,其结果将在N0
中的其他位置使用。但是,来电者不应该知道N1
。我想做的是:
// N0.h
namespace N0 {
typename T; // This isn't real C++.
std::unique_ptr<T> foo();
void bar(std::unique_ptr<T>&&);
}
// N0.cpp
#include "N1.h" // Get N1::T
namespace N0 {
typedef N1::T T;
...
}
也就是说,我想公开一个调用者看不到的类型,但在内部我想在不同的命名空间中实际使用一个类型。通过其他方式,有人可以直接声明namespace N0 { class T; }
而无需知道T
实际上位于N1
。
我可以将T
移动到N0
,但它确实属于N1
。
我可以用T
中的虚拟类包裹N0
,但这很难看,指针基本上应该这样做。
我可能会创建一个类N0::T
的子类N1::T
,但这似乎也很蹩脚。
N0
是否无法转发声明“我有一个类型而你不需要知道它是什么”并且该类型实际上是在不同的命名空间中?换句话说:为什么class C; class C{};
合法但class C; typedef int C;
是非法的? (同样地class C; using C = int;
或typedef C; typedef int C;
。)它们对我来说似乎基本相同,我想不出一个巧妙的模板技巧来解决它。我能想到的唯一区别是typedef版本不受Koenig查询的影响。
答案 0 :(得分:0)
我的意思是你可以这样做:
// N0.h
namespace N0 {
std::unique_ptr<T> foo();
void bar(std::unique_ptr<T>&&);
}
// N0.cpp
namespace N0 {
typedef N1::T t;
}
#include "N0.h"
namespace N0 {
// whatever...
}
答案 1 :(得分:0)
在您所描述的情况下,foo应该作为模板函数实现:
namespace N0 {
template <typename T>
std::unique_ptr<T> foo(){...};
template <typename T>
void bar(std::unique_ptr<T>&&){...};
}
你应该使用wrap / overload函数来做最后的技巧:
namespace N0 {
std::unique_ptr<N1::T> foo() { return foo<N1::T>(); }
//for bar there is no need to wrap, cause the T could be resolved by parameters.
}
答案 2 :(得分:0)
这是我提出的最好的,这似乎有效。我仍然觉得应该有办法不使用“技巧”使N1::T
完全隐藏在呼叫者之外:
// N0.h
#pragma once
#include <memory>
namespace N0 {
struct OpaqueObject { virtual ~OpaqueObject() {} };
std::unique_ptr<OpaqueObject> foo();
void bar(std::unique_ptr<OpaqueObject>&&);
}
//N0.cpp
#include "N1.h"
namespace N0 {
std::unique_ptr<OpaqueObject> foo() { return std::unique_ptr<N1::T>(new N1::T()); }
void bar(std::unique_ptr<OpaqueObject> &&) {}
}
// N1.h
#pragma once
#include "N0.h"
namespace N1 {
class T : public N0::OpaqueObject {};
}
// test.cpp
#include "N0.h"
int main() {
auto x = N0::foo();
N0::bar(std::move(x));
}