Display two types at compile time

I have a set of types related to a one to one relationship, for example:

TypeA ---> Type1 TypeB ---> Type2 TypeC ---> Type3 

I know this relation at compile time.

Then I have a template class that depends on these two types:

 template<class T1,class T2> class MyClass { T1 foo; T2 bar; }; 

Now the user of my library will print something like:

 MyClass<TypeA,Type1> x; 

This is inconvenient because there is a dependency between the two types, and it should be enough for the user to specify only the first type.

In addition, mixing the two types should not be possible:

 MyClass<TypeA,Type2> y; //it should not compile 

I am not very familiar with meta-programming of templates, I got the impression that this is a doable task, but I could be wrong.

The number of types involved is large, but I am happy to run a script to generate the code, if necessary.

Do you know if this is possible, or am I wasting my time? Do you have any ideas to point me in the right direction?

+6
source share
3 answers
 template<class T> struct get_mapped; template<> struct get_mapped<TypeA>{ typedef Type1 type; }; // and so on.... template<class T> class MyClass{ typedef typename get_mapped<T>::type T2; T foo; T2 bar; }; 
+6
source
 template<class T> struct TypeLetter2TypeDigit; template<> struct TypeLetter2TypeDigit<TypeA> { typedef Type1 type; }; template<> struct TypeLetter2TypeDigit<TypeB> { typedef Type2 type; }; template<> struct TypeLetter2TypeDigit<TypeC> { typedef Type3 type; }; template<class T1> // Type2 is not needed class MyClass { // Type2 is deduced. typedef typename TypeLetter2TypeDigit<T1>::type T2; T1 foo; T2 bar; }; 
+5
source

Why not just create a shell type:

 template <typename T1, typename T2> struct wrapper { typedef T1 type1; typedef T2 type2; }; typedef wrapper<TypeA, Type1> TypeX; typedef wrapper<TypeB, Type2> TypeY; typedef wrapper<TypeC, Type3> TypeZ; 

The user then says MyClass<TypeX>; , and you define:

 template <typename T> class MyClass { typename T::type1 foo; typename T::type2 bar; }; 

If you want to protect against misuse of the template, use partial specialization:

 template <typename> class MyClass; // undefined template <typename S, typename T> class MyClass<wrapper<S,T>> { S foo; T bar; }; 

This approach can be easily extended to include additional compile-time data in the wrapper class. Alternatively, you can use std::pair with the member types first_type and second_type .

+3
source

Source: https://habr.com/ru/post/899128/


All Articles