38

I am currently creating a class with a constexpr constructor and I wonder if I can use an std::array to store the data of this class. Does the standard explicitly specify that an std::array has a constexpr constructor and that its contents can be accessed at compile-time ?

4
  • std::array does not have a constexpr constructor to the best of my knowledge Commented Jan 10, 2013 at 21:18
  • 10
    std::array has no (user-defined) constructor. It's an aggregate. Commented Jan 10, 2013 at 21:21
  • 1
    Note that although you can store the data, you'll have a harder time extracting it in a constexpr way. Commented Jan 10, 2013 at 21:28
  • 2
    There are several library defect reports out that add constexpr to various functions. So you cannot get your data in a constexpr manner in C++11 but this should be resolved in the next language version (and possibly sooner depending on your library implementor) to mark most of them (all?) as constexpr. Commented Jan 10, 2013 at 21:46

2 Answers 2

43

Because std::array<T, N> is an aggregate, it can be initialized as a constexpr if and only if the underlying type T has a constexpr constructor (when presented with each initializer you provide).

Sign up to request clarification or add additional context in comments.

Comments

13

Based on the comment by @MarkGlisse: this compiles

#include <array> 
#include <iostream>

template<typename T, std::size_t N> 
struct X 
{ 
   constexpr X(const std::array<T,N>& a):arr(a){} 

   private: 
   std::array<T,N> arr; 
}; 

constexpr std::array<int,2> a {{ 13, 18 }}; 
constexpr X<int,2> x = a;

int main() 
{        
}

I believe I have found the relevant quote from the Standard here:

12.1 Constructors [class.ctor]

6 A default constructor that is defaulted and not defined as deleted is implicitly defined when it is odrused (3.2) to create an object of its class type (1.8) or when it is explicitly defaulted after its first declaration. The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement. If that user-written default constructor would be ill-formed, the program is ill-formed. If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr.

This looks essentially like @BenVoigt's answer.

5 Comments

#include <cstdlib> #include <array> template<typename T, std::size_t N> struct X { constexpr X(std::array<T,N>& a):arr(a){} private: std::array<T,N> arr; }; std::array<int,2> a = { 13, 18 }; X<int,2> x = a; compiles for me...
@MarcGlisse Try adding constexpr in front of a and X, and it won't compile!
#include <cstdlib> #include <array> template<typename T, std::size_t N> struct X { constexpr X(const std::array<T,N>& a):arr(a){} private: std::array<T,N> arr; }; constexpr std::array<int,2> a = { 13, 18 }; constexpr X<int,2> x = a; compiles just fine.
@MarcGlisse OK, tnx, so any clue why it compiles? ;-)
chris said it, std::array is an aggregate. What part exactly confuses you?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.