(C++) 我的自定义数组无法初始化(编译错误)

Posted

技术标签:

【中文标题】(C++) 我的自定义数组无法初始化(编译错误)【英文标题】:(C++) My custom array cannot be initialized (compile error) 【发布时间】:2018-07-20 05:41:30 【问题描述】:

我创建了一个继承 std::array 的自定义数组。 但它不能使用 std::array 的相同语句初始化。 谁能告诉我为什么这不起作用并帮助我正确修改我的代码?

这里是编译错误信息:

main.cpp: In function 'int main()':
main.cpp:32:35: error: no matching function for call to 'my_array::my_array()'
     my_array<int, 2>   b  1, 2 ; // compile error
                                   ^
main.cpp:13:8: note: candidate: my_array::my_array()
 struct my_array : std::array<T,N>
        ^
main.cpp:13:8: note:   candidate expects 0 arguments, 1 provided
main.cpp:13:8: note: candidate: constexpr my_array::my_array(const my_array&)
main.cpp:13:8: note:   no known conversion for argument 1 from '' to 'const my_array&'
main.cpp:13:8: note: candidate: constexpr my_array::my_array(my_array&&)
main.cpp:13:8: note:   no known conversion for argument 1 from '' to 'my_array&&'

下面是我的实现代码。 提前致谢。


#include<iostream>
#include<array>

template<typename T, std::size_t N>
struct my_array : std::array<T,N>

    T& operator[](std::size_t n)
    
        if(!(n < N))
            std::cout << "out of range" << std::endl;
        return (*static_cast<std::array<T,N>*>(this))[n];
    
    const T& operator[](std::size_t n) const
    
        if(!(n < N))
            std::cout << "out of range" << std::endl;
        return (*static_cast<const std::array<T,N>*>(this))[n];
    
;

int main(void)

    std::array<int, 2> a  1, 2 ; // no error
    my_array<int, 2>   b  1, 2 ; // compile error

【问题讨论】:

与您的问题无关,但 operator[] 函数没有边界检查是有原因的。如果您想要边界检查,请改用at if(n > N) it is out of bound 看起来你在做相反的事情。 很确定你已经违反了在 C++17 之前的编译器中使用基类聚合初始化的规则。试图找到确切的裁决。没有太多机会使用 C++17。 通常,如果有人询问编译错误,必须将它们包含在问题中(通常,它们会准确说明问题所在)。 【参考方案1】:

我会说您的自定义类不知道带有参数 initializer_list 的构造函数,因此您必须自己实现它。

基于您的代码的快速而肮脏的解决方案,但编译和执行:

#include<iostream>
#include<array>
#include <initializer_list>

template<typename T, std::size_t N>
struct my_array : std::array<T,N>

  my_array(std::initializer_list<T> list)
    
      int i=0;
      for(auto val = list.begin();val != list.end();val++) 
        std::array<T,N>::at(i++) = *val;
      
    


  T& operator[](std::size_t n)
    
      if(n < N)
        std::cout << "out of range" << std::endl;
      return (*static_cast<std::array<T,N>*>(this))[n];
    
  const T& operator[](std::size_t n) const
    
      if(n < N)
        std::cout << "out of range" << std::endl;
      return (*static_cast<const std::array<T,N>*>(this))[n];
    
;

int main(void)

  std::array<int, 2> a  1, 2 ; // no error
  my_array<int, 2>   b  1, 2 ; // compile error
  std::cout << b.at(0) << ", " << b.at(1) << std::endl;

希望这会有所帮助。

【讨论】:

【参考方案2】:

std::array 使用Aggregate Initialization。不幸的是,在 C++17 之前,具有基类的类不能是聚合,这消除了 my_array

来自 N3291 中的 [dcl.init.aggr](我有最早的 C++11 后标准草案)

聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数 (12.1),没有用于非静态数据成员 (9.2) 的大括号或均衡器,没有私有或受保护的非静态数据成员(第 11 条),无基类(第 10 条),无虚函数 (10.3)。

C++14 稍微弱化了这些要求(N4140)

聚合是一个数组或类(第 9 条),没有用户提供的构造函数 (12.1),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),并且没有虚函数(10.3)。

对基类的限制仍然存在。

当前标准修订将相关段落改写为

聚合是一个数组或一个类(第 12 条),具有

(1.1) — 没有用户提供的、显式的或继承的构造函数 (15.1),

(1.2) — 没有私有或受保护的非静态数据成员(第 14 条),

(1.3) — 没有虚函数 (13.3),并且

(1.4) — 没有虚拟、私有或受保护的基类 (13.1)。

允许public 基类

AltruisticDelay 的答案通过std::Initializer_list 解决了这个限制。如果您在选择编译器或标准支持方面受到限制,这可能是您的正确答案。

如果您可以编译成 C++17 或更新的标准,则问题中发布的代码无需修改即可编译。

【讨论】:

以上是关于(C++) 我的自定义数组无法初始化(编译错误)的主要内容,如果未能解决你的问题,请参考以下文章

linux中的c++编译错误

如何调试并进入转换为 C++ 的自定义语言源?

由于 int main() 函数的定义错误,C++ 编译器拒绝了我的代码

急求c语言 dev c++) 利用结构体做一个小系统,为啥直接无法编译运行?

为什么iOS 8上的SceneKit无法编译我的自定义着色器?

在 C++ 中使用指针初始化 char 数组或字符串