簡體   English   中英

使用嵌套的 class 作為父 class 模板參數?

[英]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> dT* 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM