eudaemonia
eudaemonia

Reputation: 3

Using constant struct members in array declaration

I am writing a small toy project (a datastructure) where I have a collection of constants that I would like to bundle in an anonymous struct that lives in the main class. This class uses some of the constants to declare the size of static arrays. It looks somewhat like this:

template< class T, size_t K >
class Tree {
    static struct {
        size_t const min_keys{ K };
        size_t const max_keys{ 2*K };
        ...
    } const constants;
    ...
};

K is a template parameter, and all the members of the struct are const. However, the compiler (I am using g++ 5.1) complains when declaring an static array.

bpt.h:34:34: error: size of array is not an integral constant-expression
     T keys[constants.max_keys];

This confuses me – everything is const. I am merely trying to clean up my constants, bundling them like this seemed ideal and interesting. Using an enum class would be nice too, but as the class also needs to compare against those constants, is out of the question. Right now I am using an anonymous enum which does work, but this has stirred my curiosity.

Why is this? Is this a bad idea? I am very new to C++ – I would be thrilled to see alternatives.

Upvotes: 0

Views: 448

Answers (1)

Kerrek SB
Kerrek SB

Reputation: 476970

The following code works:

#include <cstddef>
#include <iostream>

template <typename T, std::size_t K>
struct Tree {
    static constexpr struct {
    //     ^^^^^^^^^
        std::size_t const min_keys{ K };
        std::size_t const max_keys{ 2*K };
    } constants {};
    //         ^^^
};

Example usage:

int main()
{
    int foo[Tree<int, 20>::constants.min_keys] = {1, 2};
}

The key point is to make Tree::constants a constexpr static data member, which means that its members are constant expressions that can be used as, say, array sizes. Note:

  • static constexpr members need initializers, hence the {} (or we could have put {K, 2 * K} here and left off the brace-or-equal initializers).

  • You don't need a definition for the static constexpr member as long as you don't odr-use it (e.g. don't try to compute &Tree<int, 3>::constants). This is convenient.

Upvotes: 1

Related Questions