模板元程序将类型转换为唯一编号

dar*_*rak 11 c++ templates metaprogramming

我刚开始玩元编程,我正在研究不同的任务,只是为了探索这个领域.其中之一是生成一个唯一的整数并将其映射到类型,如下所示:

int myInt = TypeInt<AClass>::value;
Run Code Online (Sandbox Code Playgroud)

其中value应该是编译时常量,而后者可以在元程序中进一步使用.

我想知道这是否可能,在这种情况下如何.因为虽然我已经学到很多关于探索这个问题的知识,但我还是没有找到答案.

(PS答案是/否答案比不使用元编程的c ++解决方案更令人满意,因为这是我正在探索的领域)

sbi*_*sbi 8

原则上,这是可能的,虽然解决方案可能不是您正在寻找的.

简而言之,您需要提供从类型到整数值的显式映射,每种可能的类型都有一个条目:

template< typename T >
struct type2int
{
   // enum { result = 0 }; // do this if you want a fallback value
};

template<> struct type2int<AClass> { enum { result = 1 }; };
template<> struct type2int<BClass> { enum { result = 2 }; };
template<> struct type2int<CClass> { enum { result = 3 }; };

const int i = type2int<T>::result;
Run Code Online (Sandbox Code Playgroud)

如果您不在基本模板中提供回退实现,则对于未知类型将失败T,否则它将返回回退值.

根据您的具体情况,也可能有其他可能性.例如,您可以在类型本身内定义这些数字:

class AClass {
  public:
    enum { inta_val = 1 };
  // ...
};

class BClass {
  public:
    enum { inta_val = 2 };
  // ...
};

// ... 

template< typename T >
struct type2int
{
   enum { result = T::int_val }; // will fail for types without int_val
};
Run Code Online (Sandbox Code Playgroud)

如果您提供更多上下文,也可能有其他解决方案.

编辑:

实际上没有任何更多的背景.我正在调查它是否真的可行,但没有分配数字本身.

我认为迈克的排序理念是一种很好的方法(同样,对于一组固定的类型),而不必明确地指定数字:它们是由排序隐式给出的.但是,我认为使用类型列表会更容易.列表中任何类型的索引都是其编号.我认为以下内容可能会:

// basic type list manipulation stuff
template< typename T1, typename T2, typename T3...>
struct type_list;

// meta function, List is assumed to be some instance of type_list
template< typename T, class List >
struct index_of {
  enum { result = /* find index of T in List */ };
};

// the list of types you support
typedef type_list<AClass, BClass, CClass> the_type_list;

// your meta function
template< typename T >
struct type2int
{
   enum { result = index_of<T, the_type_list>::result };
};
Run Code Online (Sandbox Code Playgroud)


Mat*_*ann 7

这样做你想要的.根据需要分配值.它利用了分配函数中静态的方式.

inline size_t next_value()
{
     static size_t id = 0;
     size_t result = id;
     ++id;
     return result;
}

/** Returns a small value which identifies the type.
    Multiple calls with the same type return the same value. */
template <typename T>
size_t get_unique_int()
{
     static size_t id = next_value();
     return id;
}
Run Code Online (Sandbox Code Playgroud)

它不是类固醇的模板元编程,但我认为这是一件好事(相信我!)

  • 但这不会在编译时生成值,这是此任务的目的. (2认同)

小智 6

与Michael Anderson的方法类似,但此实现完全符合标准,可以在编译时执行.从C++ 17开始,看起来constexpr值将被允许用作其他模板元编程目的的模板参数.此外,unique_id_type可以与==,!=,>,<等进行比较以进行排序.

// the type used to uniquely identify a list of template types
typedef void (*unique_id_type)();

// each instantiation of this template has its own static dummy function. The
// address of this function is used to uniquely identify the list of types
template <typename... Arguments>
struct IdGen {
   static constexpr inline unique_id_type get_unique_id()
   {
      return &IdGen::dummy;
   }

private:
   static void dummy(){};
};
Run Code Online (Sandbox Code Playgroud)

  • 这可以在共享库中安全使用吗?如果我有两个共享库A和B都调用IdGen <int> :: get_unique_id(),我可以确定它们获得相同的值吗? (2认同)

Dou*_* T. 3

到目前为止,我最接近的是能够保留类型列表,同时跟踪返回基地的距离(给出唯一值)。请注意,如果您正确跟踪事物,此处的“位置”对于您的类型将是唯一的(请参阅示例的 main )

template <class Prev, class This>
class TypeList
{
public:
   enum
   {
      position = (Prev::position) + 1,
   };
};

template <>
class TypeList<void, void>
{
public:
  enum
  {
     position = 0,
  };
};


#include <iostream>

int main()
{
        typedef TypeList< void, void> base;  // base
        typedef TypeList< base, double> t2;  // position is unique id for double
        typedef TypeList< t2, char > t3; // position is unique id for char

        std::cout << "T1 Posn: " << base::position << std::endl;
        std::cout << "T2 Posn: " << t2::position << std::endl;
        std::cout << "T3 Posn: " << t3::position << std::endl;

}
Run Code Online (Sandbox Code Playgroud)

这是可行的,但我自然不想以某种方式指定“prev”类型。最好找到一种自动跟踪这一点的方法。也许我会再玩一会儿,看看是否可行。绝对是一个有趣/有趣的谜题。