1

I created a custom array inheriting std::array. But it cannot be initialized using the same statement for std::array. Could anyone let me know why this does not work and help me out to correctly modify my code?

Here is the compile error messages :

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&&'

Below is the code for my implementation. Thanks in advance.


#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
}
4
  • 3
    Unrelated to your problem, but the operator[] functions are without bounds-checking for a reason. If you want bounds-checking use at instead. Commented Jul 20, 2018 at 5:46
  • if(n > N) it is out of bound looks like you are doing opposite. Commented Jul 20, 2018 at 5:56
  • Pretty sure you've run afoul of rules against using aggregate initialization with a base class in a pre-C++17 compiler. Trying to find the exact ruling. Haven't had much opportunity to use C++17. Commented Jul 20, 2018 at 5:58
  • Typically, if one asks about compilation errors, one must include them into the question (they, typically, state exactly what's wrong). Commented Jul 20, 2018 at 5:59

2 Answers 2

1

I would say your custom class doesn't know about a constructor with parameter initializer_list so you have to implement this on your own.

A quick and dirty solution based on your code, but compiling and executing:

#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;
}

Hope this helps.

answered Jul 20, 2018 at 6:18
Sign up to request clarification or add additional context in comments.

Comments

1

std::array uses Aggregate Initialization. Unfortunately until C++17 a class with a base cannot be an aggregate, and that eliminates my_array.

From [dcl.init.aggr] in N3291 (earliest post C++11 standard draft I have available)

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equalinitializers for non-static data members (9.2), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

C++14 weakens these requirements a little (N4140)

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

The restrictions against base classes remains.

Current Standards revisions rewrite the relevant paragraph into

An aggregate is an array or a class (Clause 12) with

(1.1) — no user-provided, explicit, or inherited constructors (15.1),

(1.2) — no private or protected non-static data members (Clause 14),

(1.3) — no virtual functions (13.3), and

(1.4) — no virtual, private, or protected base classes (13.1).

Which allows public base classes

AltruisticDelay's answer works around this limitation with a std::Initializer_list. If you are restricted in your choice of compilers or Standard support, this is probably the right answer for you.

If you can compile into C++17 or a more recent Standard, the code posted in the question will compile without modification.

answered Jul 20, 2018 at 6:23

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.