ZivS
ZivS

Reputation: 2124

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 convert_to_* into a convert 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);
Foo(convert(e1));

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);
Foo(convert_to<MyEnum2>(e1));

1- Is it possible to avoid the convert 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 convert_to_x)

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

Upvotes: 0

Views: 3629

Answers (1)

Tomek Sowiński
Tomek Sowiński

Reputation: 863

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;
}

Upvotes: 2

Related Questions