编译模板参数的计时/编号

Compile time counting/numbering of template parameter

本文关键字:编号 参数 编译      更新时间:2023-10-16

对于一个低级别的应用程序,我在编译时将某种索引定义为一种类型:

template <int IDX_, class T_>
class Idx{
  using TYPE = T_;
  static const int IDX = IDX_;
}

用法如下:

using region1_field1 = Idx<0, double>;
using region1_field2 = Idx<1, double>;
using region1_field3 = Idx<2, float>;
using region2_field1 = Idx<0, char>;
using region2_field2 = Idx<1, char>;

这个Idx模板基本上对我来说做得很好,但你必须手动设置IDX_参数,这很烦人,也有点危险有没有办法在编译时自动计算和设置该参数如您所见,region1_*region2_*需要该计数器的多个实例。

最后,该类用于类似以下内容:

template <class IDX_>
typename IDX_::TYPE getValue(IDX_ idx, int pos){
  return (reinterpret_cast<typename IDX_::TYPE*>(data_ptrs[IDX_]))[pos];
}

在我看来,您正在寻找boost::mpl::vector

所以我会这么做(考虑到我只是试图想象你的用例):

必要的boost::mpl:

#include <boost/mpl/vector.hpp>
#include <boost/mpl/pair.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/int.hpp>

因此,您可以拥有自己的"区域":

using region1 = boost::mpl::vector<double, double, float>;
using region2 = boost::mpl::vector<char, char>;

并且Idx类具有Idx<region1,1>快捷方式:

template <typename Region, int Pos>
using Idx = boost::mpl::pair<Region,boost::mpl::int_<Pos>>;

并且访问Idx类型:

template <typename Idx>
using IdxType = typename boost::mpl::at<typename Idx::first, typename Idx::second>;

现在-它是如何工作的:

我想象你的数据处理程序是这样的(简化版;):

struct DataPtrs
{
    char data[20]= "Hello from MPL";
    template <typename Idx>
    void* operator[](Idx idx)
    {
        return data;
    }
};
DataPtrs data_ptrs;

并且访问它-将这样看:

template <class Idx>
typename IdxType<Idx>::type getValue(int pos)  {
    return reinterpret_cast<typename IdxType<Idx>::type*>(data_ptrs[Idx()])[pos];
}

main:

#include <iostream>
int main() {
    using region2_0 = Idx<region2,0>;
    std::cout << getValue<region2_0>(1);
}

所以——我的建议——使用boost::mpl——或者如果你不能在项目中使用boost,可以从中复制必要的部分。当然,你必须根据你的需要调整我的建议。。。

最后,您可以在ideone 上尝试所有操作

将标签struct foo {};设为空。

将它们存储在template<class...>struct types{};的类型列表中。

将其存储在template<class Names, class T>struct field{};类型的字段中。

Get-value在相关字段的Names类型列表中搜索标记。

不变量,比如每个标记出现一次,以及查找中使用的每个标记都在Names中使用,可以在编译时进行检查。

您甚至可以创建一个包含缓冲区位置信息的字段集合,以允许get value在不被告知的情况下从标记中查找缓冲区,并强制执行跨字段标记的唯一性。