std::array 实现上的隐式构造函数的奇怪错误

Posted

技术标签:

【中文标题】std::array 实现上的隐式构造函数的奇怪错误【英文标题】:Weird error for implicit constructor on std::array implementation 【发布时间】:2021-06-28 02:29:15 【问题描述】:
#include "array.hpp"

int main() 
    constexpr array<int, 5> a1 =   2, 4, 6, 8  ;

这是我的代码^

我搜索了一下,据说隐式构造函数可以像这样 blah, blah, blah ,但仍然没有工作。我也只是做了一个统一的大括号初始化语法(a1 = 2, 4, 6, 8 ),但没有奏效。

错误:

main.cpp: In function ‘int main()’:
main.cpp:5:57: error: could not convert ‘2, 4, 6, 8’ from ‘<brace-enclosed initializer list>’ to ‘const xstl::array<int, 5>’
    5 |     constexpr xstl::array<int, 5> a1 =   2, 4, 6, 8  ;
      |                                                         ^
      |                                                         |
      |                                                         <brace-enclosed initializer list>
main.cpp:6:57: error: could not convert ‘1, 3, 5, 7’ from ‘<brace-enclosed initializer list>’ to ‘const xstl::array<int, 5>’
    6 |     constexpr xstl::array<int, 5> a2 =   1, 3, 5, 7  ;
      |                                                         ^
      |                                                         |
      |                                                         <brace-enclosed initializer list>

由于构造函数是隐式的,我不明白错误?

为什么这个聚合错误?为什么std::array 实现有效而此实现无效?

这里是实现,不多说:

#ifndef HEADER_ARRAY_HPP
#define HEADER_ARRAY_HPP

#include <cstddef>
#include <iterator>
#include <stdexcept>

template <class T, std::size_t N>
struct array 
    using value_type = T;
    using size_type = std::size_t;
    using difference_type = std::ptrdiff_t;
    using reference = value_type&;
    using const_reference = const value_type&;
    using pointer = value_type*;
    using const_pointer = const value_type*;
    using iterator = value_type*;
    using const_iterator = const value_type*;
    using reverse_iterator = std::reverse_iterator<iterator>;
    using const_reverse_iterator = std::reverse_iterator<const_iterator>;

    const_reference at(size_type pos) const 
        return pos < size() ? Data[pos] : throw std::out_of_range("");
    

    const_reference operator[](size_type pos) const 
        return Data[pos];
    

    reference front() 
        return *begin();
    

    const_reference front() const 
        return *begin();
    

    reference back() 
        return *std::prev(end());
    

    const_reference back() const 
        return *std::prev(end());
    

    T *data() noexcept 
        return Data;
    

    const T *data() const noexcept 
        return Data;
    

    iterator begin() noexcept 
        return Data;
    

    const_iterator begin() const noexcept 
        return Data;
    

    const_iterator cbegin() const noexcept 
        return Data;
    

    iterator end() noexcept 
        return Data + size();
    

    const_iterator end() const noexcept 
        return Data + size();
    

    const_iterator cend() const noexcept 
        return Data + size();
    

    reverse_iterator rbegin() noexcept 
        return reverse_iterator(end());
    

    const_reverse_iterator rbegin() const noexcept 
        return const_reverse_iterator(end());
    

    const_reverse_iterator crbegin() const noexcept 
        return const_reverse_iterator(end());
    

    reverse_iterator rend() noexcept 
        return reverse_iterator(begin());
    

    const_reverse_iterator rend() const noexcept 
        return const_reverse_iterator(begin());
    

    const_reverse_iterator crend() const noexcept 
        return const_reverse_iterator(begin());
    

    constexpr bool empty() const noexcept 
        return begin() == end();
    

    constexpr size_type size() const noexcept 
        return N;
    

    constexpr size_type max_size() const noexcept 
        return N;
    

    void fill(const T& value) 
        size_type i = 0;

        for (; i < size(); i++) 
            Data[i] = value;
        
    

    void swap(array& other) noexcept 
        size_type i;

        for (i = 0; i < other.size(); i++) 
            other.Data[i] = Data[i];
        

        for (i = 0; i < size(); i++) 
            Data[i] = other.Data[i];
        
    

private:
    T Data[N];
;

#endif // HEADER_ARRAY_HPP

【问题讨论】:

【参考方案1】:

std::array 是一个聚合,具有隐式声明的构造函数,它按照aggregate initialization 的规则初始化数组。聚合条件之一是,聚合没有私有或受保护的直接非静态数据成员。

您所期望的封闭数组的聚合初始化是不可能的,因为Data 是私有的。将data 设为公共类成员,您就可以使示例工作。

【讨论】:

std::array 是一个聚合,它没有定义任何构造函数,它依赖于aggregate-initialization,它不适用于私有成员。

以上是关于std::array 实现上的隐式构造函数的奇怪错误的主要内容,如果未能解决你的问题,请参考以下文章

避免构造函数中的隐式转换。 'explicit' 关键字在这里没有帮助

boost::optional<std::string> 和 char[] 的隐式构造函数

java 中使用jmx对tomcat实时监控默认的构造方法无法处理的异常类型的隐式超级构造函数抛出异常

C++ 类的隐式转换

C ++:从另一个构造函数隐式调用构造函数

C++关键字之:explicit