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

Accessing a member in a template: how to check if the template is a pointer or not?

本文关键字:检查 指针 是否是 成员 访问 何检查      更新时间:2023-10-16

给定以下声明:

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:确定如果类型是一个指针在模板函数

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

但是这太啰嗦了。有更好的主意吗?

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

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!
}

最好的办法可能是为指针类型专门化你的类。

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 ...
  }
}