存储任意(但恒定)长度的 std::arrays 集
Storing set of std::arrays of any (but constant) length
有没有办法存储一组 std::arrays 的任何(但恒定)长度,数组的长度稍后可以在 constexpr 中使用?
我想标准容器是不可能的,但不知何故可能有一个模板解决方案。所有信息都在编译时可用,不是吗?
示例代码:
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
// Class storing an array of any (but constant) size
struct A {
const std::vector<std::string> container;
const int container_size;
A(const std::vector<std::string>& v, int size) : container(v), container_size(size) { }
};
int main() {
// List of variable length const arrays and their sizes
std::vector<A> myAList {
A({ std::string("String1"), std::string("String2") }, 2),
A({ std::string("String1") }, 1)
};
// How would I go about using the size of each array in a constexpr?
for (auto const& a : myAList) {
// Example constexpr:
// somefunc(std::make_index_sequence<a.container_size>{});
// 2nd example converting to actual std::array
// std::array<std::string, a.container_size> arr;
// std::copy_n(std::make_move_iterator(a.begin()), a.container_size, arr.begin());
}
return 0;
}
更新:
我们要求提供更多详细信息,所以这里开始吧。我真的不关心数组是如何定义的,任何有用的东西......使用的确切 constexpr 是示例代码中的那个,std::make_index_sequence<CONSTEXPR>{}
。 我只知道我有一组在编译时定义的常量数组,应该可以在 constexpr.
的其他地方以某种方式引用它们的长度
哎呀,实际上我只要存储长度就可以了:
// Class storing an array size
struct A {
A(int size) : container_size(size) { }
const int container_size;
};
int main() {
// List of lengths
std::vector<A> mySizeList { 2, 1 };
for (auto const& a : mySizeList) {
// somefunc(std::make_index_sequence<a.container_size>{});
}
return 0;
}
我想你想要的是像 dynarray
这样垂死的东西。
你当然不能在常量表达式中使用它的大小,因为它不是编译时常量(这就是名称中的 "dyn" 所指的内容)。
要在常量表达式中使用 container_size
类型 A
必须是文字类型,所以它必须有一个 constexpr
构造函数,这将很难如果你想传递给它 vector
!
你可以做这样的事情,但它很恶心:
#include <array>
struct A
{
void* ap;
std::size_t n;
template<std::size_t N>
constexpr A(std::array<int, N>& a) : ap(&a), n(N) { }
template<std::size_t N>
std::array<int, N>& get() const { return *static_cast<std::array<int, N>*>(ap); }
constexpr std::size_t size() const { return n; }
};
int main()
{
static std::array<int, 3> a{ 1, 2, 3 };
constexpr A aa(a);
constexpr int len = aa.size(); // OK, this is a constant expression
std::array<int, aa.size()>& r = aa.get<aa.size()>();
}
这假设你想用 const&
到 std::vector
和 index_sequence
调用 somefunc
,并且你只想调用 [=11] =].它还提供对具有扩展签名的 somefunc
的支持(只需传递带有 return 值 and/or 的第三个参数,附加参数将在 std::vector<T> const&
之后传递) .
如果传入的大小比向量长,则无法将向量的大小与传入的大小对齐将导致错误。
它还假定您知道在构造时调用的是什么函数。自然地,这可以推广到您想在构造时调用的任何有限函数集。
使用的技术称为"type erasure" 或"run-time concepts"。我删除了在构造期间使用相关索引序列调用 some_func
的概念,并将删除的操作存储在 f
.
中
template<size_t N>
using size=std::integral_constant<size_t, N>;
template<
class T, template<class...>class Operation,
class Sig=std::result_of_t<Operation<size<0>>(std::vector<T> const&)>()
>
struct eraser;
template<class T, template<class...>class Operation, class R, class...Args>
struct eraser<T,Operation, R(Args...)> {
std::vector<T> data;
R(*f)(eraser const*, Args&&...);
R operator()(Args...args)const{
return f(this, std::forward<Args>(args)...);
}
template<size_t N>
eraser( std::initializer_list<T> il, size<N> ):
eraser( il.begin(), size<N>{} )
{}
template<class...Ts>
eraser( T t0, Ts... ts ):
eraser(
{std::forward<T>(t0), std::forward<Ts>(ts)...},
size<sizeof...(ts)+1>{}
)
{}
template<size_t N>
eraser( T const* ptr, size<N> ):
data(ptr, ptr+N),
f([](eraser const*self, Args&&...args)->R{
return Operation<size<N>>{}(self->data, std::forward<Args>(args)...);
})
{}
};
template<class T, size_t ... Is>
void some_func( std::vector<T> const&, std::index_sequence<Is...>) {
std::cout << "called! [#" << sizeof...(Is) << "]\n";
}
template<class N>
struct call_some_func {
template<class T>
void operator()(std::vector<T> const& v) const {
some_func( v, std::make_index_sequence<N{}>{} );
}
};
int main() {
using A = eraser<std::string, call_some_func>;
// List of variable length const arrays and their sizes
std::vector<A> myAList {
A({ std::string("String1"), std::string("String2") }, size<2>{}),
A({ std::string("String1") }, size<1>{})
};
std::cout << "Objects constructed. Loop about to start:\n";
// How would I go about using the size of each array in a constexpr?
for (auto const& a : myAList) {
a();
}
}
有没有办法存储一组 std::arrays 的任何(但恒定)长度,数组的长度稍后可以在 constexpr 中使用?
我想标准容器是不可能的,但不知何故可能有一个模板解决方案。所有信息都在编译时可用,不是吗?
示例代码:
#include <iostream>
#include <string>
#include <vector>
#include <array>
#include <algorithm>
// Class storing an array of any (but constant) size
struct A {
const std::vector<std::string> container;
const int container_size;
A(const std::vector<std::string>& v, int size) : container(v), container_size(size) { }
};
int main() {
// List of variable length const arrays and their sizes
std::vector<A> myAList {
A({ std::string("String1"), std::string("String2") }, 2),
A({ std::string("String1") }, 1)
};
// How would I go about using the size of each array in a constexpr?
for (auto const& a : myAList) {
// Example constexpr:
// somefunc(std::make_index_sequence<a.container_size>{});
// 2nd example converting to actual std::array
// std::array<std::string, a.container_size> arr;
// std::copy_n(std::make_move_iterator(a.begin()), a.container_size, arr.begin());
}
return 0;
}
更新:
我们要求提供更多详细信息,所以这里开始吧。我真的不关心数组是如何定义的,任何有用的东西......使用的确切 constexpr 是示例代码中的那个,std::make_index_sequence<CONSTEXPR>{}
。 我只知道我有一组在编译时定义的常量数组,应该可以在 constexpr.
哎呀,实际上我只要存储长度就可以了:
// Class storing an array size
struct A {
A(int size) : container_size(size) { }
const int container_size;
};
int main() {
// List of lengths
std::vector<A> mySizeList { 2, 1 };
for (auto const& a : mySizeList) {
// somefunc(std::make_index_sequence<a.container_size>{});
}
return 0;
}
我想你想要的是像 dynarray
这样垂死的东西。
你当然不能在常量表达式中使用它的大小,因为它不是编译时常量(这就是名称中的 "dyn" 所指的内容)。
要在常量表达式中使用 container_size
类型 A
必须是文字类型,所以它必须有一个 constexpr
构造函数,这将很难如果你想传递给它 vector
!
你可以做这样的事情,但它很恶心:
#include <array>
struct A
{
void* ap;
std::size_t n;
template<std::size_t N>
constexpr A(std::array<int, N>& a) : ap(&a), n(N) { }
template<std::size_t N>
std::array<int, N>& get() const { return *static_cast<std::array<int, N>*>(ap); }
constexpr std::size_t size() const { return n; }
};
int main()
{
static std::array<int, 3> a{ 1, 2, 3 };
constexpr A aa(a);
constexpr int len = aa.size(); // OK, this is a constant expression
std::array<int, aa.size()>& r = aa.get<aa.size()>();
}
这假设你想用 const&
到 std::vector
和 index_sequence
调用 somefunc
,并且你只想调用 [=11] =].它还提供对具有扩展签名的 somefunc
的支持(只需传递带有 return 值 and/or 的第三个参数,附加参数将在 std::vector<T> const&
之后传递) .
如果传入的大小比向量长,则无法将向量的大小与传入的大小对齐将导致错误。
它还假定您知道在构造时调用的是什么函数。自然地,这可以推广到您想在构造时调用的任何有限函数集。
使用的技术称为"type erasure" 或"run-time concepts"。我删除了在构造期间使用相关索引序列调用 some_func
的概念,并将删除的操作存储在 f
.
template<size_t N>
using size=std::integral_constant<size_t, N>;
template<
class T, template<class...>class Operation,
class Sig=std::result_of_t<Operation<size<0>>(std::vector<T> const&)>()
>
struct eraser;
template<class T, template<class...>class Operation, class R, class...Args>
struct eraser<T,Operation, R(Args...)> {
std::vector<T> data;
R(*f)(eraser const*, Args&&...);
R operator()(Args...args)const{
return f(this, std::forward<Args>(args)...);
}
template<size_t N>
eraser( std::initializer_list<T> il, size<N> ):
eraser( il.begin(), size<N>{} )
{}
template<class...Ts>
eraser( T t0, Ts... ts ):
eraser(
{std::forward<T>(t0), std::forward<Ts>(ts)...},
size<sizeof...(ts)+1>{}
)
{}
template<size_t N>
eraser( T const* ptr, size<N> ):
data(ptr, ptr+N),
f([](eraser const*self, Args&&...args)->R{
return Operation<size<N>>{}(self->data, std::forward<Args>(args)...);
})
{}
};
template<class T, size_t ... Is>
void some_func( std::vector<T> const&, std::index_sequence<Is...>) {
std::cout << "called! [#" << sizeof...(Is) << "]\n";
}
template<class N>
struct call_some_func {
template<class T>
void operator()(std::vector<T> const& v) const {
some_func( v, std::make_index_sequence<N{}>{} );
}
};
int main() {
using A = eraser<std::string, call_some_func>;
// List of variable length const arrays and their sizes
std::vector<A> myAList {
A({ std::string("String1"), std::string("String2") }, size<2>{}),
A({ std::string("String1") }, size<1>{})
};
std::cout << "Objects constructed. Loop about to start:\n";
// How would I go about using the size of each array in a constexpr?
for (auto const& a : myAList) {
a();
}
}