有没有办法在数组大小中以多态方式使用新的std::array
类型?也就是说,如果我有一个
void DoSomething(std::array<int, 5>& myArray) {
/* ... */
}
然后在数学上定义良好以执行以下操作(即使它不是合法的C ++代码?)
std::array<int, 10> arr;
DoSomething(arr);
Imof这在数学上是明确定义的,有没有办法写std::array
使得它的数组元素是连续的并且这个代码编译?我能想到的唯一技术是有一些奇怪的模板元程序,其中std::array<T, N+1>
继承自std::array<T, N>
,但我不相信这会迫使数组元素连续。
答案 0 :(得分:5)
直接?没有。
但是,您可以使用编译时多态来实现非常相似的功能,并且可以编写一个引用包装器,以便在代码中更容易使用:
#include <array>
#include <cstddef>
template <typename T, std::size_t N>
struct ref_array_of_at_least
{
template <std::size_t M>
ref_array_of_at_least(T (&a)[M])
: data_(a)
{
static_assert(M >= N, "Invalid size");
}
template <std::size_t M>
ref_array_of_at_least(std::array<T, M>& a)
: data_(&a[0])
{
static_assert(M >= N, "Invalid size");
}
T* data_;
};
用作:
void f(ref_array_of_at_least<int, 5>) { }
int main()
{
std::array<int, 5> x;
std::array<int, 6> y;
std::array<int, 4> z;
f(x); // ok
f(y); // ok
f(z); // fail
}
(你需要向operator[]
添加一些ref_array_of_at_least
重载等,并且需要做一些工作才能使它成为正确的,但这是一个开始,证明你正在寻找的东西的可能性。)
答案 1 :(得分:2)
如果这是一项要求,则一种方法是转换运算符到所需类型:
#include <iostream>
template <typename T, int N>
struct Array
{
Array() { for (int i = 0; i < N; ++i) x[i] = 0; }
template <int N2>
operator Array<T, N2>&()
{
// for safety, static assert that N2 < N...
return reinterpret_cast<Array<T, N2>&>(*this);
}
int size() const { return N; }
T x[N];
friend std::ostream& operator<<(std::ostream& os, const Array& a)
{
os << "[ ";
for (int i = 0; i < N; ++i) os << a.x[i] << ' ';
return os << ']';
}
};
void f(Array<int, 5>& a)
{
a.x[a.size() - 1] = -1;
}
int main()
{
Array<int, 10> a;
std::cout << a << '\n';
f(a);
std::cout << a << '\n';
}
我不会推荐它:非常可怕。一个更明确的机制似乎更不容易被滥用,而且更强大 - 有点模糊:
template <size_t N2>
Array<T,N2>& slice(size_t first_index)
{
return *(Array<T,N2>*)(data() + first_index);
}
// usage...
f(a.slice<5>(3)); // elements 3,4,5,6,7.
(清理施法以获得额外的分数: - /)
答案 2 :(得分:0)
不,但你可以伪造它:
// Hide this function however you like: "detail" namespace, use "_detail"
// in the name, etc.; since it's not part of the public interface.
void f_detail(int size, int *data) {
use(data, /* up to */ data + size);
}
int const f_min_len = 5;
template<int N>
void f(int (&data)[N]) {
static_assert(N >= f_min_len);
f_detail(N, data);
}
template<int N>
void f(std::array<int, N> &data) {
static_assert(N >= f_min_len);
f_detail(N, &data[0]);
}
这是一个完整的例子,应该完全按照提供的方式工作。您只需要从int更改数据类型(或使其成为模板参数)并根据需要添加const。