我们可以根据模板参数添加好友类吗?

时间:2014-09-16 11:44:39

标签: c++ templates friend

我想知道下面这个棘手的情况是否可能:

假设我有一个模板类template <typename DTYPE> class A{};,其中DTYPE应该是uint8_tuint16_t之一,等等。我想将一个朋友类添加到{ {1}},但这个朋友类对于每个A替代品都有所不同。此外,假设不同DTYPE值的朋友类是另一个模板类的实例化,而是独立的类。

有办法吗?

4 个答案:

答案 0 :(得分:1)

您可以添加模板“代理”类FriendOfA并将其专门用于您需要的任何类型:

// actual friends
class FriendUint8 {};
class FriendUint16 {};

template<typename T> struct FriendOfA;

template<>
struct FriendOfA<uint8_t> {
    typedef FriendUint8 type;
};

template<>
struct FriendOfA<uint16_t> {
    typedef FriendUint16 type;
};

// optional helper
template <typename T>
using FriendOfA_t = typename FriendOfA<T>::type;

template<class T>
class A {
    friend typename FriendOfA<T>::type;
    // or simply
    friend FriendOfA_t<T>;
};

答案 1 :(得分:1)

我相信你正在寻找类似的东西:

#include <iostream>

struct BaseFriend 
{
    template <typename T>
    void boo(const T& t) { t.foo(); }   
};

struct BaseFriendProxy
{
    template <typename T>
    void boo(const T& t) { std::cout << "Proxy: "; t.foo(); }   
};

template <typename TType> 
struct Friend ;

template <>
struct Friend<int> {
    using T = BaseFriend;
};

template <>
struct Friend<char> {
    using T = BaseFriendProxy;
};

template <typename DTYPE> 
class A
{
private:
    friend typename Friend<DTYPE>::T;

    void foo() const 
    { std::cout << "A::foo()" << std::endl; }    
};

int main()
{
   A<int> a;
   BaseFriend bf1;
   bf1.boo(a);

   A<char> b;
   BaseFriendProxy bf2;
   bf2.boo(b);

   return 0;
}

但这只适用于C ++ 11:你不能在{+ c> 03中将friend class ...typename X::Y结合起来

答案 2 :(得分:0)

当然可以,专门化您的模板并添加您想要的任何朋友类:

#include <iostream>
using namespace std;

class base {
 public:
    virtual int getValue() = 0;
};

class friend1 {
    public:
    base* ptr;

    int getValue() {
        return ptr->getValue();
    }
};

class friend2 {
    public:
    base* ptr;

    int getValue() {
        return ptr->getValue();
    }
};

template <typename DTYPE> class A :  public base{
    public:

    A() { data = 42; }

    // No friends

    private:
    int data;

    int getValue() {
        return data;
    }
};

template <> class A<char> :  public base{
    public:

    A() { data = 44; }

    friend class friend1;

    private:
    int data;

    int getValue() {
        return data;
    }
};

template <> class A<bool> :  public base{
    public:

    A() { data = 45; }

    friend class friend2;

    private:
    int data;

    int getValue() {
        return data;
    }
};


int main()
{
    A<char> obj1;
    friend1 friend_of_obj1;
    friend_of_obj1.ptr = &obj1;
    cout << friend_of_obj1.getValue() << endl;

    A<bool> obj2;
    friend2 friend_of_obj2;
    friend_of_obj2.ptr = &obj2;
    cout << friend_of_obj2.getValue();

}

http://ideone.com/hM9x0y

答案 3 :(得分:0)

是的,朋友可以基于模板。如;

template <typename DTYPE>
struct Friend;

template <class DTYPE>
class A {
    friend struct Friend<DTYPE>;
};

对于您希望支持的类DTYPE的每个类型A(实现方式不同),您可以专门化Friend,例如;

template<>
struct Friend<uint8_t> {
    // ...
};

基本工作样本:

#include <cstdint>

using namespace std;

template<typename T>
struct Friend;

template <class T>
class A {
    friend struct Friend<T>;

    int i = 0;    
};

template<>
struct Friend<uint8_t> {
    void method() {
        A<uint8_t> a;
        a.i = 8;
    }
};

template<>
struct Friend<uint16_t> {
    void method() {
        A<uint16_t> a;
        //A<uint8_t> b; // fails to compile
        a.i = 16;
    }
};

int main()
{
    A<uint8_t> a;
    Friend<uint8_t> f;
    f.method();
}