简体   繁体   中英

Run-time type casting based on size in c++

I'm trying to recover the type of an array based on the size of its elements. I think I cannot use templates for this. Is there any way to achieve this without switch statements? Or if it is not possible without switch statements, is there a way to embed the switch statement into a class (caster). I like the caster class idea because there are many functions apart from copy that needs similar casting.

copy_region(uint8_t *, int);
copy_region(uint16_t *, int);
copy_region(uint32_t *, int);

void copier(uint8_t *ptr_element, int sz_element) {
   copy_region( caster(sz_element, ptr_element), n);
}

The switch solution I have is like this:

void copier(uint8_t *ptr_element, int sz_element) {
   switch(sz_element){
     case 1: copy_region( uint8_t*(ptr_element), n); break;
     case 2: copy_region( uint16_t*(ptr_element), n); break;
     case 4: copy_region( uint16_t*(ptr_element), n); break;
   }
}

I also thought of defining the operations as functors so that I might have a single switch statement, but the parameters for different operations are very dissimilar.

Edit:

The type information is not lost. I'm trying to implement a system (library/framework) with templated buffers. I have a base buffer class based on uint8_t as element. This class exists because I need to insert the buffers into a list. Base buffer class implements operations on these buffers. User specifies the buffer type as a template argument to the buffer class, but the library only sees the base buffer class and the type information (element size is enough to infer type).

template<int sz_element> void copier(uint8_t *ptr_element); //no definition
template<1> void copier(uint8_t *ptr_element)
{copy_region(uint8_t*(ptr_element), n);}
template<2> void copier(uint8_t *ptr_element)
{copy_region(uint16_t*(ptr_element), n);}
template<4> void copier(uint8_t *ptr_element)
{copy_region(uint32_t*(ptr_element), n);}
template<8> void copier(uint8_t *ptr_element)
{copy_region(uint64_t*(ptr_element), n);}

If the sz_element is not known at compile time, then you have to use a switch like you had in the OP.

There is no good that can come of this though. Why do you have a uint8_t* that points to arbitrary data? Get rid of that.

[EDIT] You say you have a underlying class that is a buffer of uint8_t, and the users will use inherited classes with the type info. In that case, to have sane code, you need virtual functions:

class base {
   vector<uint8_t> buffer;
public:
   virtual void copy()=0;
   virtual ~base() {}
};
template <class type>
class derived : public base {
public:
   virtual void copy() {}
   ~derived() {}
};

This will allow your library to use the functions without knowing the types, and yet no type information is lost.

I think instead of trying to achieve what you're looking to do here you should rethink your design. Go to the source and record the type of the array in a special variable at the start of your memory block - or if possible, keep the type of the pointer you're passing around as the original type of the array so you can enforce type safety better.

There aren't many options left if you're already stripped the type information from your data without providing any mechanisms for finding out what it used to be in advance.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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