基于动态选择类型的C ++模板用法 [英] C++ template usage based on selecting type dynamically

查看:42
本文介绍了基于动态选择类型的C ++模板用法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种有效的方法来调用基于特定C ++模板类型的变量动态值.目前,我不清楚如何解决此问题,除了使用大型且难看的if/else选择器来处理大量排列,如下例所示.如您所见,这并不漂亮.

I'm trying to find an efficient way to invoke a specific C++ template type based dynamic value of a variable. Currently I'm not clear on how to approach this, except by using large and ugly if/else selector for a large set of permutations as in the example below. As you can see this is not pretty.

相反,我想动态地调用合适的模板,而无需巨大的if/else选择器...

Instead I'd like to invoke suitable template dynamically without huge if/else selector...

任何来自C ++模板大师的建议都将不胜感激.

Any advise from the C++ template masters out there would be much appreciated.

// crude generic data converter template invoked based on dynamic in/out buffer type
template <class dstType, class srcType>
void ConvertCopy(unsigned char* dst, const unsigned char* src, int size)
{
    // requires same in/out buffer same dimensions
    if (typeid(srcType) != typeid(dstType)) 
    {
        dstType* c_dst = (dstType*)dst;
        srcType* c_src = (srcType*)src;
        for(int i=0;i<size;i++)
            c_dst[i] = (dstType)c_src[i];
    }
    else
        memcpy(dst, src, size * sizeof(srcType)); // Plain copy
}

void test()
{
    const int buffersize = 100;

    int inbuffer[buffersize];
    double outbuffer[buffersize];
    unsigned char* anyIn = (unsigned char*)inbuffer;
    unsigned char* anyOut = (unsigned char*)outbuffer;

    int my_in_type = 1;
    int my_out_type = 3;

    if(my_in_type == 1) { // int
        if(my_out_type == 1) ConvertCopy<int, int>(anyOut, anyIn, buffersize); // int -> int
        if(my_out_type == 2) ConvertCopy<float, int>(anyOut, anyIn, buffersize); // int -> float
        if(my_out_type == 3) ConvertCopy<double, int>(anyOut, anyIn, buffersize); // int -> double
        // ...
    }
    else if(my_in_type == 2) { // unsigned int
        if(my_out_type == 1) ConvertCopy<int, unsigned int>(anyOut, anyIn, buffersize); // unsigned int -> int
        if(my_out_type == 2) ConvertCopy<float, unsigned int>(anyOut, anyIn, buffersize); // unsignedint -> float
        if(my_out_type == 3) ConvertCopy<double, unsigned int>(anyOut, anyIn, buffersize); // unsigned int -> double
        // ...
    }
    else {}
    // ...
}

推荐答案

没有办法(缺少非常年轻的

There’s no way (short of the very young JIT proposals) to avoid a branch or lookup table: it is a feature that different specializations of a function template can have unrelated types (with some restrictions on the parameter types, especially when supporting deduction), making it implausible to support a call with a dynamic template argument in the type system even if it were known to be drawn from a small set. (Yours all happen to be void(unsigned char*,const unsigned char*,int), but for consistency the rules do not consider that.)

也就是说,可以在这种情况下,以有效地表示样板不变:

That said, the boilerplate can be expressed efficiently in cases like this where the type doesn’t vary:

template<class D>
auto copier(int s) {
  switch(s) {
  case 1: return ConvertCopy<D,int>;
  case 2: return ConvertCopy<D,unsigned>;
  // …
  }
}
void test() {
  // …
  [](int d) {
    switch(d) {
    case 1: return copier<int>;
    case 2: return copier<float>;
    case 3: return copier<double>;
    // …
    }
  }(my_out_type)(my_in_type)(anyOut,anyIn,buffersize);
}

此方法将详细程度从 O ( mn).如果您认为多余的括号集是分开的,这可能会有所帮助,因为它们 就像运行时模板参数列表".

This approach reduces the verbosity to O(m+n) from O(mn). It may help if you think of the extra sets of parentheses as being separate because they are like "runtime template argument lists".

当然有可能将其概括为从具有已知范围的有趣输入的元函数中产生任何一致类型的值.

It would of course be possible to generalize this to produce a value of any consistent type from a metafunction with (for practicality) a known range of interesting inputs.

这篇关于基于动态选择类型的C ++模板用法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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