编译时模板`std :: integral_constant`计数器 - 如何实现它?

时间:2014-09-18 15:36:32

标签: c++ templates c++11 c++14 constexpr

我有几种类型,我想" bind"编译时每种类型的std::integral_constant顺序ID值。

示例:

struct Type00 { };
struct Type01 { };
struct Type02 { };
struct Type03 { };
struct TypeXX { };
struct TypeYY { };

template<typename T> struct TypeInfo
{
    using Id = std::integral_constant<int, ???>;
};

int main()
{
     cout << TypeInfo<Type00>::Id::value; // Should always print 0
     cout << TypeInfo<Type01>::Id::value; // Should always print 1
     cout << TypeInfo<Type02>::Id::value; // Should always print 2
     cout << TypeInfo<Type03>::Id::value; // Should always print 3
     cout << TypeInfo<TypeXX>::Id::value; // Should always print 4
     cout << TypeInfo<TypeYY>::Id::value; // Should always print 5
}

问题是我不知道如何跟踪上次使用的ID 。理想情况下,我想要类似的东西:

template<typename T> struct TypeInfo
{
    using Id = std::integral_constant<int, lastUsedID + 1>;
};

有没有办法定义和跟踪编译时lastUsedID

如何解决此问题?


编辑:

澄清:

  • TypeInfo<...>需要经常在用户代码中调用。语法必须保持清晰(用户不必(需要知道&#39; sa / 手动增加)编译时间计数器)
  • Typeinfo<T>::Id::value必须始终在整个程序中返回相同的值。初始值将是&#34;绑定&#34;在第一次实例化时,lastUsedID + 1
  • 我可以使用所有C ++ 11和C ++ 14功能。
  • 在调用TypeInfo<...>之前列出所有类型不是一个合适的解决方案。

2 个答案:

答案 0 :(得分:3)

这是不可能的,很容易理解为什么:考虑两个编译单元。第一单元看到的是Type00类型,但不是Type01,而第二单元看到Type01但看不到Type00。 C ++(包括C ++ 11和C ++ 14)中没有任何内容现在可以告诉编译器在两个编译单元中这些类型的顺序。即使为链接时添加一些数据到目标文件也为时已晚,因为您要求编译时值。这是编译单元的基本概念,它对您要求的功能构成了严重障碍。

答案 1 :(得分:1)

您可以使用类型列表执行此操作:

template <typename... Ts>
struct TypeList;

template <>
struct TypeList<>
{
    static const int size = 0;
    static std::integral_constant<int, -1> indexOf(...);
};

template <typename Head, typename... Tail>
struct TypeList<Head, Tail...> : TypeList<Tail...>
{
    static const int size = sizeof...(Tail) + 1;
    static std::integral_constant<int, sizeof...(Tail)> indexOf(Head&&);
    using TypeList<Tail...>::indexOf;
};

template <typename TypeList, typename T>
using IndexOf = std::integral_constant<int,
    TypeList::size - decltype(TypeList::indexOf(std::declval<T>()))::value - 1>;

如果T中不存在List,则IndexOf<List, T>::value-1。您可以通过从签名TypeList<>::indexOf(...)中删除省略号来使此情况成为编译错误。

用法:

struct Type00 { };
struct Type01 { };
struct Type02 { };
struct Type03 { };
struct TypeXX { };
struct TypeYY { };

using MyTypeList = TypeList<
    Type00,
    Type01,
    Type02,
    Type03,
    TypeXX,
    TypeYY
>;

int main()
{
    std::cout << IndexOf<MyTypeList, Type00>::value
              << IndexOf<MyTypeList, Type01>::value
              << IndexOf<MyTypeList, Type02>::value
              << IndexOf<MyTypeList, Type03>::value
              << IndexOf<MyTypeList, TypeXX>::value
              << IndexOf<MyTypeList, TypeYY>::value;
}

Demo