0

I need to initialize a bunch of template classes by reading a "configuration file".

Template class is something like:

class generic_block {
protected:
    std::string name;
    std::size_t size;

public:
    generic_block(std::string _name, std::size_t _size)
    : name(_name)
    , size(_size)
    {
    }

    virtual ~generic_block() {}
};

template <class T> class block: public generic_block {
private:
    T           *ptr;

public:
    block(std::string _name, T *_ptr, std::size_t _size)
    : generic_block(_name, _size)
    , ptr(_ptr)
    {
    }

    virtual ~AWblock() {}
    ...
}

I have tentative issuing code:

std::map<std::string, auto> types = {
        {"uint32_t", [](char *name, int count){
            uint32_t *ary = (uint32_t *)calloc(count, sizeof(uint32_t));
            return block<uint32_t>(name, ary, count);
        }},
        {"float", [](char *name, int count){
            float *ary = (float *)calloc(count, sizeof(float));
            return block<float>(name, ary, count);
        }}
};

generic_block b = types[type](name, count);

Compilation bombs with: error: ‘auto’ not permitted in template argument, which is understandable.

Question is: what should I use instead of "auto"?

Note: in real code I plan to use a preprocessor macro to generate "types", but I'm unsure if this approach is "best practice"; comments welcome, of course.

ZioByte
  • 2,690
  • 1
  • 32
  • 68

1 Answers1

0

You can use std::function to explicitly describe the lambda:

std::map<std::string, std::function<generic_block(char*, int)>> types = {
        {"uint32_t", [](char *name, int count){
            // ...
        }},
        {"float", [](char *name, int count){
            // ...
        }}
};

auto& block_generator = types[type];
generic_block b = block_generator(name, count);

Of course, the requirement is that all functions in the map have the same signature. So unless all Ts are the same, you'll have to use generic_block instead of block<T>.

CompuChip
  • 9,143
  • 4
  • 24
  • 48
  • 2
    Note that a return type of `generic_block` will generally result in the returned value being 'sliced'. Something like `generic_block *` or, preferably, `std::unique_ptr` is probably required. – G.M. Jun 09 '22 at 13:19