ZivS ZivS - 1 year ago 37
C++ Question

C++ template convert function

Suppose the following types:

enum class MyEnum1 {};
enum class MyEnum2 {};
typedef struct MyStruct1 {};
typedef struct MyStruct2 {};

and the following (stupid) conversions:

MyEnum1 convert_to_MyEnum2(MyEnum2 e) { return MyEnum1(); }
MyEnum2 convert_to_MyEnum1(MyEnum1 e) { return MyEnum2(); }
MyStruct1 convert_to_MyStruct1(MyStruct2 s) { return MyStruct1(); }
MyStruct2 convert_to_MyStruct2(MyStruct1 s) { return MyStruct2(); }

I want to have a single convert function that takes a single type and converts it to another.

Now, since the functions always accept a single different type and are not only different by the return type, I can obviously change all the
into a
and overload this function with all the possibilities I have.

But, I don't like the idea of having user write something like:

auto e1 = convert(e2);

I want the code to be readable so I was thinking of having something like:

//make all "convert" overloads private and only expose this function
template<typename To, typename From>
To convert_to(From from)
return convert(from);

this way the code will be:

auto e1 = convert_to<MyEnum1>(e2);

1- Is it possible to avoid the
overload but still use some sort of single entry point \ single function name to achieve what I want? (i.e find some usage to existing

2- I understand this is more code-review related but what is the recommended way (if such exist) to this issue?

Answer Source

Yes, a conversion function covering multiple types with a single name can be implemented with template specialization.

enum class MyEnum1 {};
enum class MyEnum2 {};
struct MyStruct1 {};
struct MyStruct2 {};

// Unimplemented general fall-back case.
// Note: there are more civilized ways to issue a compilation error...
template<typename To, typename From>
To convert_to(From from) { return To::unimplemented_conversion; }

template<> MyEnum1 convert_to(MyEnum2 from) { return MyEnum1(); }
template<> MyEnum2 convert_to(MyEnum1 from) { return MyEnum2(); }
template<> MyStruct1 convert_to(MyStruct2 from) { return MyStruct1(); }
template<> MyStruct2 convert_to(MyStruct1 from) { return MyStruct2(); }

int main()
    MyEnum2 e2 = convert_to<MyEnum2>(MyEnum1());
    MyEnum1 e1 = convert_to<MyEnum1>(e2);
    // MyStruct1 s1 = convert_to<MyStruct1>(e2);  unimplemented conversion
    return 0;