简体   繁体   中英

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 (eg 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://rextester.com/VSXR46052 ):

#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);
                                  ^

Problems I see:

  1. You cannot use template<Enum T> auto makeTemplatedClass(T enumValue) since T is not a type. You need to use just template<Enum T> auto makeTemplatedClass() and invoke the function differently.

  2. You need to use TemplatedClass<typename EnumToPrimitiveType<T>::type> instead of just TemplatedClass<EnumToPrimitiveType<T>::type> . That is necessary since type is a dependent type.

  3. You cannot use value as a template parameter unless it is a const or constexpr .

The following program compiles and builds on my desktop.

#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() -> TemplatedClass<typename EnumToPrimitiveType<T>::type>
{
    TemplatedClass<typename EnumToPrimitiveType<T>::type> ret(5);
    return ret;
}

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

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