访问模板中的成员:如何检查模板是否为指针?

时间:2013-03-20 16:44:54

标签: c++ templates

鉴于以下声明:

template<class T>
class A {
  void run(T val) {
    val.member ...
  }
}

如果没有使用指针,此代码可以正常工作:

A<Type> a;
Type t;
a.run(t);

但使用指针会导致错误:

A<Type*> a;
Type* t = new Type();
a.run(t);

error: request for member ‘member’ which is of non-class type ‘T*’

显然,在这种情况下,必须通过->访问该成员。处理这个问题的最佳方法是什么?

我在SO上找到了一个解决方案:Determine if Type is a pointer in a template function

template<typename T>
struct is_pointer { static const bool value = false; };

template<typename T>
struct is_pointer<T*> { static const bool value = true; };

...

if (is_pointer<T>::value) val->member
else val.member

但这非常冗长。有更好的想法吗?

2 个答案:

答案 0 :(得分:3)

您可以使用一对简单的重载函数模板:

template<typename T>
T& access(T& t) { return t; }

template<typename T>
T& access(T* t) { return *t; }

然后以这种方式使用它们:

access(val).member = 42;

例如:

template<typename T>
struct A
{
    void do_it(T& val)
    {
        access(val).member = 42;
    }
};

struct Type
{
    int member = 0;
};

#include <iostream>

int main()
{
    A<Type> a;
    Type t;
    a.do_it(t);
    std::cout << t.member << std::endl;

    A<Type*> a2;
    Type* t2 = new Type(); // OK, I don't like this, but just to show
                           // it does what you want it to do...
    a2.do_it(t2);
    std::cout << t2->member;

    delete t2;             // ...but then, don't forget to clean up!
}

这是live example

答案 1 :(得分:2)

最好的想法可能是将类专门用于指针类型。

template<class T>
class A{ ...}; 

template<>
class A<T*> { //implement for pointers
};

如果您觉得这太冗长,可以使用get_ref函数重载:

template<class T> T& get_ref(T & r) {return r;}
template<class T> T& get_ref(T* r) {return *r;}

template<class T>
class A {
   void do(T val) {
     get_ref(val).member ...
  }
}