鉴于以下声明:
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
但这非常冗长。有更好的想法吗?
答案 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 ...
}
}