【问题标题】:Compile time counting/numbering of template parameter模板参数的编译时间计数/编号
【发布时间】:2015-09-15 18:44:57
【问题描述】:

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

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];
}

【问题讨论】:

  • 您希望索引成为类型的一部分(现在是因为您将其用作模板参数),还是只希望 IDX 成员自动增加?
  • 第二个参数T_有什么意义?是否可以将其固定为适当的类型,例如std::size_t
  • @JoachimPileborg:如果它是自动递增的并保持静态和常量就好了。
  • 常量0,1,20,1的模式不一致。什么时候增加它,什么时候从零开始?如何决定?
  • 为什么不region1_field&lt;2&gt;

标签: c++ templates c-preprocessor


【解决方案1】:

在我看来,您正在寻找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&lt;region1,1&gt; 快捷方式:

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 尝试一下

【讨论】:

    【解决方案2】:

    让你的标签struct foo {};为空。

    将它们存储在template&lt;class...&gt;struct types{}; 类型列表中。

    将其存储在 template&lt;class Names, class T&gt;struct field{}; 类型字段中。

    在相关字段的名称类型列表中获取标签的值搜索。

    不变量,例如每个标签出现一次,并且在查找中使用的每个标签都在名称中使用,可以在编译时检查。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-11
      • 1970-01-01
      • 2015-10-21
      相关资源
      最近更新 更多