7

是否有可能以某種方式使部分模板規範成爲朋友類?即考慮你有下面的模板類C++模板:部分模板規範和朋友類

template <class T> class X{ 
    T t; 
}; 

現在您有部分特例,例如,用於指針

template <class T> class X<T*>{ 
    T* t; 
}; 

我想做到的是,每一個可能的X<T*>是朋友類X<S>爲ANY S。即X<A*>應該是X<B>的好友。

當然,我想過在X常用模板友元聲明:

template <class T> class X{ 
    template <class S> friend class X<S*>; 
} 

然而,這並不編譯,G ++告訴我:

test4.cpp:34:15:錯誤:的 'template<class T> class X' 專業化必須出現在命名空間範圍

test4.cpp:34:21:錯誤:偏特 'X<S*>' 宣佈 '朋友'

這是不可能的或有一些解決方法?

爲什麼我問的原因是我需要X<T*>一個構造函數,從任意X<S>創建此類(S必須是T亞型)。

的代碼看起來是這樣的:

template <class T> class X<T*>{ 
    T* t; 

    template<class S> 
    X(X<S> x) : t(&(x.t)) {} //Error, x.t is private 
} 

現在,編譯器會抱怨,當然,前提是x.t不是在看得到的構造,因爲它是私有的。這就是爲什麼我需要一個部分專業化的朋友班。

+1

「get」函數真的沒有問題嗎?這對我來說似乎更加清潔,並避免了所有模板朋友的瘋狂。 – pmr

+0

它可能會在這個例子中工作。但是,可能有數據不應公開給公衆,而只能是模板專業化。問題是如果這種行爲有可能以某種方式。 – gexicide

回答

3

在C++中,您可以在四個級別上授予超出private的訪問權限。

  • 完全public訪問(見PMR的答案)繼承層次內
  • 接入(protected,這裏無關緊要)
  • 的基本模板friend(看到這個答案)
  • 到一個非模板或完全專業friend(太弱解決你的使用情況)

沒有中間道路的選擇看看後兩種友誼。

從C++標準的§14.5.4開始:

Friend declarations shall not declare partial specializations.

下面的聲明將允許你實現你所需要的。它可以讓你自由地從任何其他專業中獲得你的模板的任何專長,但仍然只能在X之內。它比你所要求的稍寬一些。

template<class T> class X 
{ 
    template<class Any> friend class X; 
    public: 
     ... 
}; 
1

我們可以定義在十

#include <type_traits> 

template <class T> class X{ 
    T t; 
public: 
    struct Key { 
    template<typename S> 
    Key(const X<S>&) { 
     static_assert(std::is_pointer<S>::value, "Not a pointer"); 
    } 
    }; 

    const T& get(Key) const { return t; } 
    T& get(Key) { return t; } 
}; 

template <class T> class X<T*> { 
    T* t; 
public: 
    template<class S> 
    X(X<S>& x) : t(&(x.get(typename X<S>::Key(*this)))) {} 
}; 

int main() 
{ 
    X<int> x1; 
    X<int*> x2(x1); 
    return 0; 
} 

定義由密鑰保護的getter這仍然有一些弱點。 X<T*>的每個人現在可以使用 get。但是,現在這樣混淆了,沒有人會認識到這一點 。我會選擇一個簡單的公共獲得者。

+1

基本上,每個使用'nullptr'的人都可以使用'get'。看起來我們在這裏有一個允許比賽的比賽。 –

+0

@JirkaHanika你可以嘗試用'null_ptr'重載來解決這個問題,但是它不會讓它變得更好。 – pmr

+1

是的,每個使用'0'的人都可以使用'get'。 –