我有一个带有n个成员变量的类T,例如
class T{
ushort name;
ushort id;
double value;
.....etc...
};
我还有T1,T2 ......类的集合,每个类都包含成员变量 这是T成员变量的子集(因为缺少一个更好的词,让我打电话 这是T)的子集类型。例如,T1可能是
class T1 {
ushort name;
double value;
};
刚刚选出了T的两名成员。
我想写一个方法
template <typename X>
T join(T t, X x)
我们返回一个类型为T的类,通过用t替换每个成员变量的值 x的那些(假设X是T的子类型),t的其他值保持不变。
我可以想到通过专业化来做到这一点。但是应该有一种优雅的方法(可能会检测X类型是T的子集类型并做正确的事情)。
答案 0 :(得分:0)
我可以想到通过专业化来做到这一点。但是应该有一种优雅的方法(可能会检测X类型是T的子集类型并做正确的事情)。
“侦测”是专业化的一部分。您应该为“subset”-types提供特化,并且不提供泛型特化的实现(当有人使用该方法使用其他类型时,会引发编译错误。)
答案 1 :(得分:0)
如果您不想为所有子集类型提供特化。如果您使用MSVC,可以尝试使用成员检测器惯用法:Member Detector或 __ if_exist 。 因此,您只需要编写[T] * 2个宏中的成员数(如果使用MSVC,则不需要SetXXX),而不是专门编写T中所有可能的成员组合
CREATE_MEMBER_DETECTOR(name);
CREATE_MEMBER_DETECTOR(id);
CREATE_MEMBER_DETECTOR(value);
......
template<int N, typename T, typename R>
class SetName
{
public:
void operator()(T& t, R& r)
{
}
};
template<typename T, typename R>
class SetName<1, T, R>
{
public:
void operator()(T& t, R& r)
{
t.name = r.name;
}
};
......
(can be macros too)
join()应该是:
template <typename SUBSET>
T join(T t, SUBSET x)
{
SetName<Detect_name<SUBSET>::value, T, SUBSET>()(t, x);
SetValue<Detect_value<SUBSET>::value, T, SUBSET>()(t, x);
......
return t;
}
答案 2 :(得分:0)
试试这个:
#include <iostream>
#include <typeifo>
using namespace std;
template<typename T>
struct SetBase
{
T first;
T second;
SetBase(const T& first = T(), const T& second = T())
: first(first), second(second) {}
};
template<typename T>
struct Set : public SetBase<T>
{
short name_id;
Set(const T& first = T(), const T& second = T(), const short& name) :
SetBase<T>(first, second), name_id(name){}
};
template<typename Class, typename BaseClass>
Class* join(Class **a, BaseClass *b)
{
if(typeid(Class) != typeid(BaseClass))
{
Class* retval = new Class(*static_cast<Class*>(b));
retval->name_id = (*a)->name_id;
*a = retval;
}
else
{
Class* retval = new Class(*b);
*a = retval;
}
return retval;
}
int main()
{
Set<int> *a = new Set<int>(1, 2, 3);
SetBase<int> *b = new SetBase<int>(4, 5);
cout << join(&a, b)->first << " " << join(&a, b)->second << " " << join(&a, b)->name_id << "\n";
cout << a->first << " " << a->second << " " << a->name_id << "\n";
return 0;
}
Set类是从SetBase派生的公共类,所以我使用的强制转换是有效的
答案 3 :(得分:0)
我会实现从T1 ... Tn到T的转换(或者从T派生的某个类,并且具有实际设置成员的信息),然后根据T实现join()函数。不要认为这实际上是模板魔术的好地方