C ++用其他类型的值替换成员变量

时间:2011-12-23 15:53:30

标签: c++ templates types

我有一个带有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的子集类型并做正确的事情)。

4 个答案:

答案 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()函数。不要认为这实际上是模板魔术的好地方