简体   繁体   中英

C++: Get a type from (not of) a class instance

Consider an abstract class ImageSource , that represents image data in RGB format. There may be different implementation with a different color depths. One implementation could choose a pixel representation like

struct Pixel{
    uint8_t red;
    uint8_t green;
    uint8_t blue;
};

or another one like

struct Pixel{
    uint8_t red : 2;
    uint8_t green : 2;
    uint8_t blue : 2;
    uint8_t : 2;
};

I would like to create ImageSource in a way that I can get the structure representing the pixel data from the class definition, just like in this sample:

void debugPixel(ImageSource &source){
    //ImageSource is abstract, each implementation may use a different pixel structure
    uint8_t *data = source->getBuffer();
    for(uint16_t i = 0; i < source->getWidth() * source->getHeight() * sizeof(source::Pixel); i += sizeof(source::Pixel)){
        source::Pixel *pixel = data[i];
        std::cout << "red: " << pixel->red << ", green: " << pixel->green << ", blue: " << pixel->blue;
    }
}

ImageSource could be defined like this

class ImageSource{
public:
    virtual uint8_t* getBuffer() = 0;
    virtual uint16_t getHeight() const = 0;
    virtual uint16_t getWidth() const = 0;
};

Is there any way to retrieve a type (the Pixel structure) from a class if I only have an instance of it (I don't know which type ImageSource actually is)?

In your example above you want to print the data in a specific way, based on the type. I'm sure you'll have other methods as well.

Move Pixel to a class (you could leave it as a struct as well, very close to a class in C++), and implement an output operator for each different type of Pixel object. Implement whichever other methods you need specific to the Pixel type inside the Pixel as well.

Then, you let the language determine the type and correct method for you.

You can use specialized templates.

As an example (ie, you'd need to create a specific example for each type of Pixel -- here I generalized with bool and int ):

   template <typename T> 
   struct Print
   {
      static void print (const T v, FILE *op=(stdout))
      { return; }
   };

   template <> 
   struct Print<bool>
   {
      static void print (const bool v, FILE *op=(stdout))
      { fprintf (op, "%u", v); return; }
   };

   template <>
   struct Print<int>
   {
      static void datafile (const int v, FILE *op=(stdout))
      { fprintf (op, "%d", v); return; }
   };

Which you would use as follows:

#include <typeinfo>
void printPixel(Pixel *pixel)
{
   Print<typeid(pixel->red)>::print(pixel->red);
   return;
}

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