Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/149.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 数组大小是否协变?_C++_Arrays_C++11_Polymorphism - Fatal编程技术网

C++ 数组大小是否协变?

C++ 数组大小是否协变?,c++,arrays,c++11,polymorphism,C++,Arrays,C++11,Polymorphism,是否有一种方法可以在数组大小中多态地使用新的std::array类型?也就是说,如果我有一个形式的函数 void DoSomething(std::array<int, 5>& myArray) { /* ... */ } void DoSomething(std::array和myArray){ /* ... */ } 那么数学上定义好了做以下(即使它不是合法C++代码)< /P> std::数组arr; 剂量测定法(arr); 如果这在数学上定义得很好,有没

是否有一种方法可以在数组大小中多态地使用新的
std::array
类型?也就是说,如果我有一个形式的函数

void DoSomething(std::array<int, 5>& myArray) {
    /* ... */
}
void DoSomething(std::array和myArray){
/* ... */
}

那么数学上定义好了做以下(即使它不是合法C++代码)< /P>

std::数组arr;
剂量测定法(arr);
如果这在数学上定义得很好,有没有一种方法可以编写
std::array
,这样它的数组元素是连续的,并且代码可以编译?我能想到的唯一技术是使用一些奇怪的模板元程序,
std::array
继承自
std::array
,但我不认为这会直接强制数组元素是连续的。

?没有

但是,您可以使用编译时多态性来实现非常类似的功能,并且您可以编写一个引用包装器,使其更易于在代码中使用:

#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_;
};
#包括
#包括
模板
至少\u的结构引用\u数组\u
{
模板
至少(T&a)[M]的参考数组
:数据(a)
{
静态断言(M>=N,“无效大小”);
}
模板
至少引用数组中的数组(std::array&a)
:数据(&a[0])
{
静态断言(M>=N,“无效大小”);
}
T*数据;
};
用作:

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
}
void f(ref\u数组至少\u的\u){
int main()
{
std::数组x;
std::数组y;
std::数组z;
f(x);//好的
f(y);//好的
f(z);//失败
}

(您需要添加一些
操作符[]
重载等内容到
ref\u array\u of_至少
,并且需要做一些工作才能使其保持正确,但这是一个开始,证明了您正在寻找的可能性。)

不,但您可以伪造它:

// 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]);
}
//隐藏此函数,不管您喜欢什么:“detail”名称空间,使用“\u detail”
//以名义等。;因为它不是公共界面的一部分。
无效f_详图(整数大小,整数*数据){
使用(数据,/*至*/数据+大小);
}
int const f_min_len=5;
模板
无效f(整数和数据)[N]){
静态断言(N>=f\u min\u len);
f_详细信息(N,数据);
}
模板
空f(标准::数组和数据){
静态断言(N>=f\u min\u len);
f_详细信息(N,&数据[0]);
}

这是一个完整的示例,应该完全按照前面介绍的那样工作。您只需将数据类型从int更改为int(或使其成为模板参数),并根据需要添加const。

如果这是一项要求,一种方法是将运算符转换为所需类型:

#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';
}
#包括
模板
结构数组
{
数组(){for(inti=0;ifriend std::ostream&Operator如果您想要编译时多态性,为什么不在
N
上模板化函数,或者如果您想要运行时多态性,为什么不使用
std::vector
?@Karl Knechtel-假设我想要一个总是包含“至少五个元素”或“至少十个元素”的数组的函数我可以用模板来实现这一点,但这会导致大量代码重复,并且需要
static\u assert
-风格的代码,这并不优雅。我不能用
std::vector
静态检查这一点。因此,让函数接受某个大小的数组的想法是一种尝试,类似于C99静态大小的数组参数这可以在编译时检查。我不确定您的示例。具体来说,我不确定我是否理解您所说的“数学上定义良好”的意思。在
DoSomething
中,如果您查询
std::distance(myArray.begin(),myArray.end())
,你期望结果是什么?
5
10
?@James McNellis-我认为“数学上定义良好”意味着“数组是类型理论数学意义上数组的一个子类型。”我希望它能给出10,因为这是数组的实际长度。@templatetypedef:如果它给出10,那么它就不是数组。如果DoSomething用于其他大小的数组,那么它就不应该将数组作为参数。这是简单的Liskov替换主要内容…不要弄乱。
#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.