Using the std :: initializer_list constructor without creating ambiguities?

I have a class called Shapethat can be initialized from any iterable and a class with a name Arraythat just contains Shape. However, I get a compilation error, which I cannot explain when I try to initialize Array:

class Shape
{
public:
    template<typename Iterator>
    Shape(Iterator first, Iterator last)
        : m_shape(first, last) {}

    template <typename Iterable>
    Shape(const Iterable& shape)
        : Shape(shape.begin(), shape.end()) {}

    template<typename T>
    Shape(std::initializer_list<T> shape)
        : Shape(shape.begin(), shape.end()) {}

private:
    std::vector<std::size_t> m_shape;
};

class Array
{
public:
    Array(const Shape& shape)
        : m_shape(shape) {}
private:
    Shape m_shape;
};

int main() {
    Shape s{0};       // ok
    Array a1({1, 2}); // ok
    Array a2({0});    // error
}

A compilation error appears in the second constructor Shape:

prog.cxx:35:16:   required from here
prog.cxx:14:23: error: request for member ‘beginin ‘shape’, which is of non-class type ‘const int
         : Shape(shape.begin(), shape.end()) {}
                 ~~~~~~^~~~~
prog.cxx:14:38: error: request for memberendin ‘shape’, which is of non-class type ‘const int
         : Shape(shape.begin(), shape.end()) {}
                                ~~~~~~^~~

I don’t understand what is going on here. Why is a constructor initializer_list<T>called instead of a constructor Iterable? What is the difference between a constructor Shapewith {0}and a constructor Array?

+4
source share
1 answer

, gcc , . :

Array a2({0});

Array {0}.

№1:

Array(Shape const& );

- Shape {0}, std::initializer_list<int> - std::initializer_list .

. № 2:

Array(Array&& );

. , , , Array {0}, . , Shape 0 ( ), - accept-all-the-things. , .

, :

  • №1: {0} --> Shape
  • № 2: 0 --> Shape --> Array

, .


, , . , , is_constructible_v<Shape, int> ...

+3

Source: https://habr.com/ru/post/1687349/


All Articles