问题
I have a set of types related with a one-to-one relation, for example:
TypeA ---> Type1
TypeB ---> Type2
TypeC ---> Type3
I know these relation at compile time.
Then, I have a template class that depends on this two types:
template<class T1,class T2>
class MyClass
{
T1 foo;
T2 bar;
};
Now, the user of my library will type 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 specify only the first type.
Also, mixing the two types shouldn't be possible:
MyClass<TypeA,Type2> y; //it should not compile
I am not very familiar with template meta programming, I got the impression that this is doable task, but I may be wrong.
The number of types involved is big, however I am happy to run a script to generate the code if necessary.
Do you know if it is possible or I am wasting my time? Do you have any ideas to point me on the right direction?
回答1:
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;
};
回答2:
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;
};
回答3:
Why not just create a wrapper 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;
Then the user says, MyClass<TypeX>;
, and you define:
template <typename T>
class MyClass
{
typename T::type1 foo;
typename T::type2 bar;
};
If you want to guard against misuse of the template, use a partial specialization:
template <typename> class MyClass; // undefined
template <typename S, typename T>
class MyClass<wrapper<S,T>>
{
S foo;
T bar;
};
This approach can easily be extended to include further compile-time data into the wrapper class. Alternatively, you could use std::pair
with member types first_type
and second_type
instead.
来源:https://stackoverflow.com/questions/7739877/map-two-types-at-compile-time