c++ - 如何将编译时 std::array “扩展”为参数包?
问题描述
我想使用部分模板专业化来将数组(在编译时创建)“分解”为由其值组成的参数包(与我在代码中定义的其他结构交互)。以下(我的第一次尝试)未编译
#include <array>
template <typename T, auto k> struct K;
template <typename T, std::size_t... A> struct K<T, std::array<std::size_t, sizeof...(A)>{A...}> {};
因为模板参数std::array<long unsigned int, sizeof... (A)>{A ...}
不能涉及模板参数。据我了解,如果非类型参数非常依赖模板参数,则不可能在部分模板特化中提供非类型参数。因此,我尝试通过在类型中包含值来解决此问题:
#include <array>
template <auto f> struct any_type;
template <typename T, typename array_wrapper> struct FromArr;
template <typename T, std::size_t... A>
struct FromArr<T, any_type<std::array<std::size_t, sizeof...(A)>{A...}>> {};
int main() {
FromArr<int, any_type<std::array<std::size_t, 2>{1, 2}>> d;
(void) d;
}
但是,在这里,当我尝试使用它时,部分模板专业化失败了;上面的定义与我使用它的方式不匹配,我不确定为什么。它失败并出现以下错误:
file.cc: In function ‘int main()’:
file.cc:10:55: error: aggregate ‘FromArr<int, Any<std::array<long unsigned int, 2>{std::__array_traits<long unsigned int, 2>::_Type{1, 2}}> > d’ has incomplete type and cannot be defined
10 | FromArr<int, Any<std::array<std::size_t, 2>{1, 2}>> d;
是否可以解决这个问题/使用不同的方法将数组作为参数包进行接口?
使用的编译器
我使用g++-10.0 (GCC) 10.0.1 20200124 (experimental)
和编译 via g++ -std=c++2a file.cc
,因为我使用非类型模板参数,所以需要 c++2a。
编辑:
描述如何处理数组
在我的真实代码中,我有一个结构,它依赖于——除其他外——一个参数包(1)。如果我能够使用数组 (2)(我在另一段代码中将其作为非类型模板参数)与该结构交互,那就太好了,如下面的代码所示。
template <int... s> struct toBeUsed; // (1)
template <std::size_t s, std::array<int, s> arr> struct Consumer { // (2)
toBeUsed<arr> instance; // This is what I would like to do
}
我的尝试是编写一个如上所述的辅助结构FromStruct
,我可以用一个实例化它array
,其中我有一个 typedef FromStruct::type
,它提供toBeUsed
了正确的参数,类似于这个例子,它用 std:: 类型做我想做的事情元组是由。
链接到示例
在这里,我链接了简化的使用示例(第二个代码块)。
解决方案
受@dfri 回答的启发,我将她/他的解决方案转换为可以省略函数的版本,而是仅使用一个使用部分模板专业化的结构,std::integer_sequence
这对其他人可能也很有趣:
template <auto arr, template <typename X, X...> typename Consumer,
typename IS = decltype(std::make_index_sequence<arr.size()>())> struct Generator;
template <auto arr, template <typename X, X...> typename Consumer, std::size_t... I>
struct Generator<arr, Consumer, std::index_sequence<I...>> {
using type = Consumer<typename decltype(arr)::value_type, arr[I]...>;
};
完整的用法示例:
#include <array>
/// Structure which wants to consume the array via a parameter pack.
template <typename StructuralType, StructuralType... s> struct ConsumerStruct {
constexpr auto operator()() const { return std::array{s...}; }
};
/// Solution
template <auto arr, template <typename X, X...> typename Consumer,
typename IS = decltype(std::make_index_sequence<arr.size()>())> struct Generator;
template <auto arr, template <typename X, X...> typename Consumer, std::size_t... I>
struct Generator<arr, Consumer, std::index_sequence<I...>> {
using type = Consumer<typename decltype(arr)::value_type, arr[I]...>;
};
/// Helper typename
template <auto arr, template <typename T, T...> typename Consumer>
using Generator_t = typename Generator<arr, Consumer>::type;
// Usage
int main() {
constexpr auto tup = std::array<int, 3>{{1, 5, 42}};
constexpr Generator_t<tup, ConsumerStruct> tt;
static_assert(tt() == tup);
return 0;
}
推荐阅读
- charts - chartjs默认背景颜色到列
- jquery - 使用 jQuery CSS 在 Botframework 中更改自适应卡片
- java - 重构 for 循环和错误(类型不匹配:无法从元素类型 String 转换为 Integer)
- .htaccess - 从类别内的 url 中删除/签名
- c# - 识别字符串内容,并验证
- amazon-s3 - 在单键和多键分区雅典娜中哪个性能更高?
- python - 我应该在运行新程序时编辑 VS Code 的环境吗
- javascript - 在 ref 中渲染 ReactPortal
- jquery - jQuery隐藏具有匹配文本或数据属性的TR
- mongodb - 克隆 MongoDB 以运行测试