samedi 4 mars 2017

Map enum value to template argument in C++

I have an enum class with several members. The goal of the enum is to encode primitive types (e.g. int, long, float, ...) at runtime, so that it's possible to store this information in a database for example. At the same time a lot of classes templated to work on primitive types exist as well.

The problem: I want to create an object from such a templated class, given an enum value that is not a constant. Would this be possible in any way that is cleaner and more scalable than creating a long switch on the enum values (or doing essentially the same with a map as proposed in the answer of Dynamic mapping of enum value (int) to type)?

Here's something I've been trying hoping that template type inference could work, but it fails to compile (can be checked here for example: http://ift.tt/2mPPjRk):

#include <iostream>

enum class Enum {
    Int,
    Long
};

template<Enum T>
struct EnumToPrimitiveType;

template<>
struct EnumToPrimitiveType<Enum::Int> {
    using type = int;
};

template<>
struct EnumToPrimitiveType<Enum::Long> {
    using type = long;
};

template<typename T>
class TemplatedClass
{
public:
    TemplatedClass(T init): init{init} {}
    void printSize() { std::cout << sizeof(init) << std::endl; }
private:
    T init;
};

template<Enum T>
auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
{
    TemplatedClass<EnumToPrimitiveType<T>::type> ret(5);
    return ret;
}

int main()
{
    Enum value{Enum::Int};
    auto tmp = makeTemplatedClass(value);
    tmp.printSize();
}

Compile error:

source_file.cpp:36:27: error: expected ‘)’ before ‘enumValue’
 auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
                           ^
source_file.cpp:36:6: warning: variable templates only available with -std=c++14 or -std=gnu++14
 auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
      ^
source_file.cpp:36:38: error: expected ‘;’ before ‘->’ token
 auto makeTemplatedClass(T enumValue) -> TemplatedClass<EnumToPrimitiveType<T>::type>
                                      ^
source_file.cpp: In function ‘int main()’:
source_file.cpp:44:16: error: ‘A’ is not a member of ‘Enum’
     Enum value{Enum::A};
                ^
source_file.cpp:45:34: error: missing template arguments before ‘(’ token
     auto tmp = makeTemplatedClass(value);
                                  ^

Aucun commentaire:

Enregistrer un commentaire