假设我们有以下类型
template <bool... Values>
struct foo{};
Run Code Online (Sandbox Code Playgroud)
我想从constexpr数组创建一个可变参数模板bool tab[N].换句话说,我想做的事情如下:
constexpr bool tab[3] = {true,false,true};
using ty1 = foo<tab[0], tab[1], tab[2]>;
Run Code Online (Sandbox Code Playgroud)
但我想以编程方式进行.现在,我尝试了以下内容:
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>])...>;
Run Code Online (Sandbox Code Playgroud)
我甚至不确定它是否可能.也许诉诸于像Boost.Preprocessor这样的东西,但我不喜欢这个想法.那么,有没有人有想法?谢谢!
编辑
我一边是constexpr布尔方形矩阵的框架,可以在编译时使用xor,否定等创建.
另一方面,我有一个模板框架,它使用布尔值作为参数,使用在可变参数模板中编码的信息静态创建操作.
我的目标是弥合这两个框架之间的差距.因此,我无法使用硬编码解决方案.
编辑2
我发现这个问题有同样的问题和一个很好的答案,这非常接近TC的一个(使用指针).该extern联动也很重要.
但是,我意识到我忘记了一个关键因素.我的bool数组包含在一个matrix结构中,可以重载运算符^,|等:
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];
}
}
Run Code Online (Sandbox Code Playgroud)
因此,如果我们应用TC的解决方案:
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;
Run Code Online (Sandbox Code Playgroud)
编译器抱怨传递一个非类型参数:
// 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_>;
Run Code Online (Sandbox Code Playgroud)
我在上面的评论中使用constexpr带有外部链接的全局变量(这是必要的,因为 GCC 不符合外部链接要求,请参阅错误 52036),如果您将其放在标头中并包含不同翻译单元中的标题。仅适用于一个翻译单元的解决方案并不是一种解决方案。一种解决方法是将矩阵存储为类的静态数据成员。
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");
Run Code Online (Sandbox Code Playgroud)
演示。另外,由于使用matrix_holder::matinty1<2, matrix_holder::mat>算作 odr-use,为了完全符合要求,您应该提供一个定义:
constexpr matrix<2> matrix_holder::mat;
Run Code Online (Sandbox Code Playgroud)