[英]Using nested class as parent class template parameter?
我有一個嵌套的 class 定義,我想作為父 class( class 包含嵌套的 class,而不是被繼承的 class )模板參數傳遞下去。 由於模板似乎不知道嵌套類的存在,我試圖將其作為不完整的類型傳遞下去,后來才發現這樣做通常是個壞主意,而且很少被允許(例如shared_ptr
)。
我知道這可以很容易地通過簡單地在外部聲明嵌套的 class 來解決(我就是這樣做的),但我問這個是因為我想了解是否有任何方法可以達到同樣的效果,因為我喜歡他們的做法不要污染命名空間它們如何與父 class 定義“關聯”而不暴露任何內容。
這是一個示例,也許可以使我在談論的內容更加清楚:
#include <memory>
using namespace std;
template <class T> class shared_class {
protected:
shared_ptr<T> d = make_shared<T>();
T* container() { return d.get(); }
};
// A is the "parent" class.
class A : public shared_class<C> { // Compiler error: C is undefined.
// Similarly, A::C will complain that no C is in A.
class C { // Nested class
public:
int i = 0;
};
};
是否有另一種使用模板的方式,即嵌套 class 的整個定義完全包含在父 class 定義中?
簡而言之:不,你不能這樣做。 您可以在 SO 上找到一些類似的問題,但這一切都歸結為能夠前向聲明嵌套類,沒有定義就無法做到這一點。 例如看這個問題。
換句話說,只要揮手,你可能會認為你可以做這樣的事情:
class A;
class A::C; // Error: not real C++
class A : public shared_class<A::C> { // Error: incomplete base class
class C {
public:
int i = 0;
};
};
但你不能。 您需要將C
的聲明分開,如果要將其用作基類,則需要對其進行定義。 另請參閱此類問題。
如果只是你最關心的命名空間封裝,你總是可以只使用一個專用的namespace
,這就是它們的用途。
據我所知,您給出的要求沒有針對您的具體案例的解決方案。
直接使用C
作為模板參數不能以任何方式工作,僅僅是因為那時編譯器還沒有看到C
被聲明為A
的成員類,並且因為在該點之前沒有辦法聲明嵌套類.
它不適用於您的特定情況,但有一些限制,您可以通過特征模板或直接通過別名聲明向shared_class
模板參數的類型添加間接,這將允許您延遲確定T
是在定義A
之前應該是C
並將C
保持為嵌套類。
不幸的是,如果您想在將使用類模板專業化實例化的聲明之一中使用shared_class
的類型T
,這不起作用,這里是shared_ptr<T> d
和T* container()
。 后者可以通過聲明返回類型auto
來保存,但前者不能。
這個想法是讓shared_class
在任何地方使用typename T::shared_class_type
而不是T
。
A
類將被定義為
class A : public shared_class<A> {
public:
class C {
public:
int i = 0;
};
using shared_class_type = C;
};
或者,您可以定義一個template<typename T> struct shared_class_traits;
, 可能具有包含using shared_class_type = typename T::shared_class_type;
的默認實現在using shared_class_type = A::C;
定義之后可能專門針對A
成員,因此shared_class
可以在任何地方使用typename shared_class_traits<T>::shared_class_type
。 這比使用shared_class_type
“保留”所有類的特定成員名稱更靈活。
但正如我在上面解釋的那樣,只要shared_class
在使用類模板特化實例化的上下文中完全使用shared_class_type
,它就不會起作用。 因此,在成員函數體或默認成員初始化程序內部會很好,但在數據成員或成員函數類型中則不行。
正如其他答案指出的那樣,這個問題沒有直接的解決方案,因為無法轉發聲明 class C。
為了仍然能夠寫A::C
我的解決方案是:
namespace {
class C_Anon{
public:
int i = 0;
};
}
template <class T> class shared_class {
protected:
shared_ptr<T> d = make_shared<T>();
T* container() { return d.get(); }
};
// A is the "parent" class.
class A : public shared_class<C_Anon> {
using C = C_Anon; //Allows for writing A::C
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.