从constexpr数组创建可变参数模板 [英] Create a variadic template from a constexpr array

查看:75
本文介绍了从constexpr数组创建可变参数模板的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我们具有以下类型

template <bool... Values>
struct foo{};

我想从 constexpr 数组 bool标签[N] 。换句话说,我想执行以下操作:

I want to create a variadic template from a constexpr array bool tab[N]. In other words, I want to do something like:

constexpr bool tab[3] = {true,false,true};
using ty1 = foo<tab[0], tab[1], tab[2]>;

但我想以编程方式进行操作。现在,我尝试了以下操作:

But I want to do it programmatically. For now, I've tried the following:

template <std::size_t N, std::size_t... I>
auto
mk_foo_ty(const bool (&tab)[N], std::index_sequence<I...>)
{
  // error: template argument for template type parameter must be a type
  return foo<tab[I]...>{};
}

// error (see mk_foo_ty)
using ty2 = decltype(mk_ty(tab, std::make_index_sequence<3>{}));

// error: expected '(' for function-style cast or type construction
using ty3 = foo<(tab[std::make_index_sequence<3>])...>;

我什至不确定是否有可能,也许可以使用Boost.Preprocessor之类的方法,我不喜欢这个主意,所以,有人有主意吗?谢谢!

I'm not even sure if it's possible. Maybe resorting to something like Boost.Preprocessor, but I don't like the idea. So, does anyone have an idea? Thanks!

EDIT

我一方面有一个 constexpr 布尔方阵的框架,可以在编译时使用xor,求反等方法创建它们。

I have on one side a framework of constexpr square matrices of booleans which can be created at compile-time using xor, negation, etc.

另一方面,我有一个模板框架,该模板使用以布尔值作为参数的可变参数模板中编码的信息来静态创建操作。

On the other side, I have a framework of templates which statically creates operations using informations encoded in variadic templates using boolean as parameters.

我的目标是

编辑2

我发现了这个问题,它具有相同的问题和很好的答案,它非常接近 TC。的(使用指针)。 外部链接也非常重要。

I've found this question with the same problem and a nice answer, which is very close to the T.C.'s one (using a pointer). The extern linkage is also very important.

但是,我意识到我忘记了一个关键要素。我的 bool 数组包含在 matrix 结构中,以便能够重载运算符^,|等:

However, I realize I forgot a key element. My bool array is contained in a matrix structure to be able to overload operators ^, |, etc.:

template <std::size_t N>
struct matrix
{
  const bool data_[N*N];

  template<typename... Values>
  constexpr matrix(Values... values) noexcept
    : data_{static_cast<bool>(values)...}
  {}

  constexpr bool operator [](std::size_t index) const noexcept
  {
    return data_[index];
  }
}

因此,如果我们应用T.C的解决方案:

Thus, if we apply T.C's solution:

template<std::size_t N, const bool (&Tab)[N], class>
struct ty1_helper;

template<std::size_t N, const bool (&Tab)[N], std::size_t... Is>
struct ty1_helper<N, Tab, std::index_sequence<Is...>>
{
  using type = foo<Tab[Is]...>;
};

template<std::size_t N, const bool (&Tab)[N]>
using ty1 = typename ty1_helper<N, Tab, std::make_index_sequence<N>>::type;

编译器抱怨传递非类型参数:

Compilers complain about passing a non-type parameter :

// error: non-type template argument does not refer to any declaration
//        using t = make_output_template<m.data_, std::make_index_sequence<3>>;
//                                       ^~~~~~~
using t = ty1<3, m.data_>;


推荐答案

我在上面的评论中使用的方式具有外部链接的全局 constexpr 变量(由于GCC的外部链接要求不合规定,因此必须使用此变量,请参见错误52036 ),如果将其放在标题中并将标题包含在不同的翻译单元中,则可能会在链接时急剧爆炸。仅对一个翻译部门有用的解决方案并不是很多解决方案。一种解决方法是将矩阵存储为类的静态数据成员。

The way I did it in the comments above, using a global constexpr variable with external linkage (necessary due to GCC's nonconforming external linkage requirement, see bug 52036), would probably blow up spectacularly at link time if you put it in a header and include the header in different translation units. A solution that's good for one translation unit only isn't much of a solution. One workaround is to store the matrix as a static data member of a class.

struct matrix_holder {
    static constexpr matrix<2> mat = {true, false, true, false};
};

template<std::size_t N, const matrix<N> &Mat, class> 
struct ty1_helper;

template<std::size_t N, const matrix<N> &Mat, std::size_t... Is>
struct ty1_helper<N, Mat, std::index_sequence<Is...>> { 
    using type = foo<Mat[Is]...>; 
};

template<std::size_t N, const matrix<N> &Mat>
using ty1 = typename ty1_helper<N, Mat, std::make_index_sequence<N*N>>::type;

static_assert(std::is_same<ty1<2, matrix_holder::mat>,
                           foo<true, false, true, false>>::value, "Oops");

演示。另外,由于在 ty1< 2中使用 matrix_holder :: mat ,所以matrix_holder :: mat> 被视为odr用途,要完全符合要求,您应该提供一个定义:

Demo. Also, since using matrix_holder::mat in ty1<2, matrix_holder::mat> counts as an odr-use, to be fully conforming you should supply a definition:

constexpr matrix<2> matrix_holder::mat;

这篇关于从constexpr数组创建可变参数模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆