繁体   English   中英

在不同种类的样本类型之间转换

[英]Convert between different kind of sample type

我想使用模板在不同样本类型之间进行转换

template<class T,class U>
void convert(const T* source, U* dest, size_t n)
    {
    do
        {
        double G=double(max(*dest))/max(*source);
        T diff=max(*source) - min(*source);
        *dest=U(makeUnsigned(*source - min(*source))*G/makeUnsigned(diff)
              +makeUnsigned(max(*source) - *source)*double(min(*dest))/makeUnsigned(diff));

        ++dest;
        ++source;
        --n;
        }
    while(n!=0);
    }

现在,我想要一个自动生成的矩阵,这样我就可以

convert[from][to](source,dest,n);

每个元素都对应正确的版本。 我知道我必须在这里强制转换函数指针(每个元素都必须是指向具有const void *,void * size_t的函数的指针,无论如何这都是等效的)。

我可以那样做吗?

首先,编写以下代码:

template<typename T, typename U>
U convert( T const& src );

因为其他所有内容都应使用模板元编程来编写。 这样做的好处是,您可以根据需要专门设置convert<int, double>convert<std::string, int>

接下来,编写:

template<typename T, typename U>
void convert_buffer( T const* src, U* dest, size_t n );

只是简单地循环调用上面的convert 我将其分为两个函数,因为可能不统一的代码进入convert ,并且调用具有可见主体的函数的开销基本上为零。

然后写这个:

typedef void(*blind_converter)(void const*, void*, size_t);
template<typename T, typename U>
void convert_blind_buffer( void const* src, void* dest, size_t n ) {
  return convert_buffer( reinterpret_cast<T const*>(src), reinterpret_cast<U*>(dest), n );
}

它封装了强制类型转换,并且不需要您进行理论上无效的指针类型强制类型转换。 它是“转换盲目的”缓冲区–盲目的,因为它需要void* s。

接下来,我们不想手动维护您的NxN阵列。 一种类型,用于存储您订购的类型列表:

template<typename... Ts>
struct type_list {};

然后我们编写一些元编程来构建NxN数组:

template<typename Src, typename DestList>
struct make_convert_one_way;
template<typename Src, typename... Ds>
struct make_convert_one_way< Src, type_list<Ds...> > {
  std::array< blind_converter, sizeof...(Ds) > operator()() const {
    return { convert_blind_buffer< Src, Ds >... };
  }
};

template<typename list>
struct make_convert_array;

template<typename... Ts>
struct make_convert_array< type_list<Ts...> > {
  std::array< std::array<blind_converter, sizeof...(Ts) >, sizeof...(Ts) > operator()() const {
    return { make_convert_one_way< Ts, type_list<Ts...> >... };
  }
};

typedef type_list< int, char, double > my_list;
auto convert_array = make_convert_array<my_list>()();

或类似的规定。

如果您的source和dest类型type_list ,则必须修改上述内容以采用两个type_list ,但是从根本上讲,这没有什么困难。

下一个有用的功能是在上面的数组中从类型映射到索引的功能,因为维护该位置应该是编译器的工作。

template<typename T, typename List, typename=void>
struct index_of;
template<typename T, typename T0, typename... Ts>
struct index_of<T, type_list<T0, Ts...>, typename std::enable_if<
  std::is_same<T, T0>::value
>::type >: std::integral_constant< std::size_t, 0 > {};
template<typename T, typename T0, typename... Ts>
struct index_of<T, type_list<T0, Ts...>, typename std::enable_if<
  !std::is_same<T, T0>::value
>::type >: std::integral_constant< std::size_t, index_of<T, type_list<Ts...>::value+1 > {};

这可以让您做到这一点:

static_assert( index_of< int, my_list >::value == 0, "all is well!" );

现在,您可能需要将其包装成某种类型的敷料。 一个策略可能看起来像这样:

template<typename List>
struct EnumDressing;
template<typename... Ts>
struct EnumDressing<type_list<Ts...>> {
  enum type {
    e_begin = 0,
    e_end = sizeof...(Ts),
  };
  template<typename T>
  static constexpr type value() {
    return static_cast<type>( index_of<T, type_list<Ts...> >::value );
  }
};

其中,我们将EnumDressing<my_list>::type作为代表您类型的整数名称的enum的类型,可以通过EnumDressing<my_list>::value<int>()获得其EnumDressing<my_list>::value<int>() 自然地,您可以使用typedef清理它:

typedef EnumDressing<my_list> Types;
typedef Types::type eType;

struct typed_array {
  eType type;
  void* buff;
  size_t n;
};
void do_convert( typed_array src, typed_array dst) {
  Assert(src.n == dst.n);
  convert_array[ src.type ][ dst.type ]( src.buff, dst.buff, std::min( src.n, dst.n ) );
}
template<typename T, size_t N>
typed_array make_typed_array( T (&arr)[N] ) {
  return { Types::value<T>(), reinterpret_cast<void*>( &arr[0] ), N };
}

int main() {
  double d[100];
  int i[100];
  do_convert( make_typed_array( d ), make_typed_array( i ) );
}

自然而实际的用例将typed_array的创建与使用分开。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM