alesegdia
alesegdia

Reputation: 548

Automatically generate unique type ID and vice versa

Regarding to this code review, is it possible to also assign a size_t to a type? i.e.:

template <size_t N>
struct IntToType {
    typedef ??? type; // ???
};

TypeID::value<int>();               // "assigns" 0 to int
IDType<0>::type;                    // resolves to int
TypeID::value<IDType<0>::type>();   // resolves to 0

I think it's just impossible by language design, this kind of recursion is probably impossible because it may depend on the order the code is being compiled, but I'll ask anyway.

It's ok to have any other way of defining an unique ID for each type if the other way around works.

Upvotes: 1

Views: 286

Answers (1)

Galik
Galik

Reputation: 48615

I'm not a templates expert by any means, so I don't know of any loopholes in this, but it seems you could hard-wire type info using template specializations as follows:

template <typename T>
struct TypeId {
};

template <>
struct TypeId<int> {
    static const size_t value = 0;
};

template <>
struct TypeId<unsigned> {
    static const size_t value = 1;
};

template <>
struct TypeId<long> {
    static const size_t value = 2;
};

template <>
struct TypeId<unsigned long> {
    static const size_t value = 3;
};

template <>
struct TypeId<float> {
    static const size_t value = 4;
};

template <>
struct TypeId<double> {
    static const size_t value = 5;
};

// ------

template <size_t N>
struct TypeInfo {
};

template <>
struct TypeInfo<TypeId<int>::value> {
    typedef int type;
    static constexpr char const* name = "int";
};

template <>
struct TypeInfo<TypeId<unsigned>::value> {
    typedef unsigned type;
    static constexpr char const* name = "unsigned int";
};

template <>
struct TypeInfo<TypeId<long>::value> {
    typedef long type;
    static constexpr char const* name = "long int";
};

template <>
struct TypeInfo<TypeId<unsigned long>::value> {
    typedef unsigned long type;
    static constexpr char const* name = "unsigned long int";
};

template <>
struct TypeInfo<TypeId<float>::value> {
    typedef float type;
    static constexpr char const* name = "float";
};

template <>
struct TypeInfo<TypeId<double>::value> {
    typedef double type;
    static constexpr char const* name = "double";
};

// ---

void func(int i)
{
    std::cout << "func int\n";
    std::cout << TypeInfo<TypeId<decltype(i)>::value>::name << '\n';
}

void func(float f)
{
    std::cout << "func float\n";
    std::cout << TypeInfo<TypeId<decltype(f)>::value>::name << '\n';
}

int main()
{
    TypeInfo<0>::type n1 = {};
    TypeInfo<4>::type n2 = {};

    func(n1);
    func(n2);

    std::cout << TypeInfo<TypeId<int>::value>::name << ": " << TypeId<int>::value << '\n';
    std::cout << TypeInfo<TypeId<unsigned>::value>::name << ": " << TypeId<unsigned>::value << '\n';
    std::cout << TypeInfo<TypeId<double>::value>::name << ": " << TypeId<double>::value << '\n';
}

Output:

func int
int
func float
float
int: 0
unsigned int: 1
double: 5

Upvotes: 2

Related Questions