I'm looking for a way to map types, f.i. having a class Double:
class Double
{
public:
typedef double basic_type;
...
};
I'd like to be able to have a type caster so that
typeid(TypeToObjectType<double>::type) == typeid(Double)
Any ideas how to accomplish this (through partial specializations etc.) ?
You can achieve this through specialization :
template<class T>
struct TypeToObjectType;
template<>
struct TypeToObjectType<double> {
typedef Double type;
};
Note that you have to provide a specialization for each of the types on which you want TypeToObjectType
to work. Macros can be helpful here :
#define SPECIALIZE_TYPETOOBJECTTYPE(ObjectType) \
template<> struct TypeToObjectType<ObjectType::basic_type> { \
typedef ObjectType type; \
};
SPECIALIZE_TYPETOOBJECTTYPE(Int)
SPECIALIZE_TYPETOOBJECTTYPE(Double)
This should work very well, however, I haven't tested this method for classes of mine. I have used an idea from the book "C++ Templates: The Complete Guide", paragraph 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;
}
EDIT:
Another one solution. More concise and flexible:
#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;
}
Sounds like you are looking for something like this:
template<typename T>
struct TypeToObjectType;
// specialization for T=double
template<>
struct TypeToObjectType<double> {
typedef Double type;
};
Here TypeToObjectType<double>::type
is Double
and you can add other specializations for additional mappings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With