根据模板参数选择联合成员 [英] select an union member depending on a template parameter

查看:121
本文介绍了根据模板参数选择联合成员的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在处理C ++中的联合,我想要一个函数模板,它根据模板参数访问活动的联合成员。

I'm dealing with an union in C++, and I would like have a function template which access to the active union member depending on a template parameter.

代码是类似的东西(doSomething只是一个例子):

Code is something like (doSomething is just an example):

union Union {
  int16_t i16;
  int32_t i32;
};

enum class ActiveMember {
    I16 
  , I32
}

template <ActiveMember M>
void doSomething(Union a, const Union b) {
  selectMemeber(a, M) = selectMember(b, M);
  // this would be exactly (not equivalent) the same
  // that a.X = b.X depending on T.
}

为了实现这一点,我只发现了一些不好的黑客,例如专业化,或者是一种不均匀的访问和分配方式。

To accomplish this I only found bad hacks like specialization, or a not homogeneous way to access and assign.

推荐答案

可能性1

而不是使用枚举,您可以使用简单的结构来选择成员:

instead of using an enum, you can use simple structs to pick the member:

typedef short int16_t;
typedef long int32_t;

union Union {
    int16_t i16;
    int32_t i32;
};

struct ActiveMemberI16 {};
struct ActiveMemberI32 {};

template <typename M>
void doSomething(Union& a, Union b) {
    selectMember(a, M()) = selectMember(b, M());

    // this would be exactly (not equivalent) the same
    // that a.X = b.X depending on T.
}

int16_t& selectMember(Union& u, ActiveMemberI16)
{
    return u.i16;
}

int32_t& selectMember(Union& u, ActiveMemberI32)
{
    return u.i32;
}

int main(int argc, char* argv[])
{
    Union a,b;
    a.i16 = 0;
    b.i16 = 1;
    doSomething<ActiveMemberI16>(a,b);
    std::cout << a.i16 << std::endl;

    b.i32 = 3;
    doSomething<ActiveMemberI32>(a,b);
    std::cout << a.i32 << std::endl;
    return 0;
}

这需要为联合中的每个成员定义一个struct和一个selectMember方法,但至少你可以使用selectMember跨越许多其他功能。

This requires to define a struct and a selectMember method for every member in the union, but at least you can use selectMember across many other functions.

请注意,我将参数转为参考,如果不适当,您可以调整此参数。

Note that I turned the arguments to references, you might adjust this if not appropriate.

可能性2

通过将union指针转换为所需的类型指针,您可以使用一个selectMember函数。

By casting the union pointer to the desired type pointer, you can go with a single selectMember function.

typedef short int16_t;
typedef long int32_t;

union Union {
    int16_t i16;
    int32_t i32;
};
template <typename T>
T& selectMember(Union& u)
{
    return *((T*)&u);
}

template <typename M>
void doSomething(Union& a, Union b) {
    selectMember<M>(a) = selectMember<M>(b);

    // this would be exactly (not equivalent) the same
    // that a.X = b.X depending on T.
}



int _tmain(int argc, _TCHAR* argv[])
{
    Union a,b;
    a.i16 = 0;
    b.i16 = 1;

    doSomething<int16_t>(a,b);
    std::cout << a.i16 << std::endl;

    b.i32 = 100000;
    doSomething<int32_t>(a,b);
    std::cout << a.i32 << std::endl;
    return 0;
}

这篇关于根据模板参数选择联合成员的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆