类型映射模板化

10

我正在寻找一种将类型映射起来的方法,例如有一个 Double 类:

class Double 
{
public:
    typedef double basic_type;
    ...
};

我希望能够有一个类型转换器,以便

typeid(TypeToObjectType<double>::type) == typeid(Double)
任何想法如何通过部分特化等途径来实现这一点?
3个回答

16

您可以通过专门化来实现这一点:

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)

谢谢,我差点就搞定了 :) 这正是我想要的。 - Robert

7
听起来你正在寻找这样的东西:
template<typename T>
struct TypeToObjectType;

// specialization for T=double    
template<>
struct TypeToObjectType<double> {
   typedef Double type;
};

这里的 TypeToObjectType<double>::typeDouble,你可以添加其他特化类型来进行额外的映射。


3

这应该非常好用,然而,我还没有测试过这种方法是否适用于我的类。我使用了来自书籍《"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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接