我正在寻找一种将类型映射起来的方法,例如有一个 Double 类:
class Double
{
public:
typedef double basic_type;
...
};
我希望能够有一个类型转换器,以便
typeid(TypeToObjectType<double>::type) == typeid(Double)
任何想法如何通过部分特化等途径来实现这一点?您可以通过专门化来实现这一点:
template<class T>
struct TypeToObjectType;
template<>
struct TypeToObjectType<double> {
typedef Double type;
};
请注意,您必须为每个要使用TypeToObjectType
的类型提供专门化。宏可以在此处提供帮助:
#define SPECIALIZE_TYPETOOBJECTTYPE(ObjectType) \
template<> struct TypeToObjectType<ObjectType::basic_type> { \
typedef ObjectType type; \
};
SPECIALIZE_TYPETOOBJECTTYPE(Int)
SPECIALIZE_TYPETOOBJECTTYPE(Double)
template<typename T>
struct TypeToObjectType;
// specialization for T=double
template<>
struct TypeToObjectType<double> {
typedef Double type;
};
这里的 TypeToObjectType<double>::type
是 Double
,你可以添加其他特化类型来进行额外的映射。
这应该非常好用,然而,我还没有测试过这种方法是否适用于我的类。我使用了来自书籍《"C++ Templates: The Complete Guide"》,第20.4.2段的一个想法。
#include <iostream>
#include <string>
#include <list>
#include <type_traits>
template<typename... Ts>
struct type_mapper;
template<>
struct type_mapper<>
{
static void mapTo(...);
};
template<typename T, typename... Ts>
struct type_mapper<T, Ts...> : type_mapper<Ts...>
{
static typename T::second_type mapTo(typename T::first_type);
using type_mapper<Ts...>::mapTo;
};
template<typename T, typename MapperT>
struct GetTypeOnMap
{
using type = decltype(MapperT::mapTo(std::declval<T>()));
};
template<typename T, typename MapperT>
using get_type_on_mapping = typename GetTypeOnMap<T, MapperT>::type;
int main(void)
{
using mapper = type_mapper <
std::pair<int, double>,
std::pair<double, int>,
std::pair<float, std::string>>;
using shouldBeDouble = get_type_on_mapping<int, mapper>;
using shouldBeString = get_type_on_mapping<float, mapper>;
std::cout << shouldBeDouble{2.9};
std::cout << shouldBeString{"Hello"};
return 0;
}
编辑:
另一种解决方案。更加简洁和灵活:
#include <complex>
#include <type_traits>
#include <cstdint>
#include <iostream>
#include <string>
template <typename V1, typename V2, typename T>
struct OnTypesEqual : std::bool_constant<std::is_same_v<V1, V2>> {
using type = T;
};
template <typename T>
struct default_type : std::true_type {
using type = T;
};
template<typename T>
using TypesMapper = typename std::disjunction<
OnTypesEqual<T, double, std::int8_t>,
OnTypesEqual<T, float, std::int16_t>,
OnTypesEqual<T, std::string, std::int32_t>,
OnTypesEqual<T, char, std::int64_t>,
default_type<void>
>::type;
int main()
{
std::cout << typeid(TypesMapper<double>).name() << std::endl;
std::cout << typeid(TypesMapper<float>).name() << std::endl;
std::cout << typeid(TypesMapper<std::string>).name() << std::endl;
std::cout << typeid(TypesMapper<char>).name() << std::endl;
return 0;
}