Thomas Russell
Thomas Russell

Reputation: 5980

Why the following non-static data member initialization is invalid in C++11

I have tried to compile the following small example:

template <typename T, std::size_t... Sizes>
class Foo {
public:
     const std::size_t    rank = sizeof...(Sizes);
     const std::size_t    dimensions[sizeof...(Sizes)] = { Sizes... };
};

int main()
{
    Foo<int, 1, 2, 3> foo;

    std::cout << "Rank: " << foo.rank << std::endl;

    return 0;
}

It does not compile with gcc-4.8.1 complaining of a lack of ; at end of member declaration and a lack of expected unqualified-id before ... token. However, if I replace the two members with the following it compiles and works as expected:

const std::size_t     rank = 5;
const std::size_t     dimensions[5] = {1, 2, 3, 4, 5};

Why can I not use sizeof... and Sizes... as compile-time constants, surely both are known and evaluated at compile time and so can be used in non-static data member initialization? Moreover, if I replace rank = 5 with rank = sizeof(int) it compiles and works as expected, so it doesn't appear to be a problem with sizeof.


Here is my demonstrative ideone.

Upvotes: 2

Views: 171

Answers (2)

Praetorian
Praetorian

Reputation: 109119

This is gcc bug 57673 that was fixed in gcc 4.9. The fix for gcc 4.8 is to add an extra set of parentheses.

const std::size_t rank = (sizeof...(Sizes));

Live demo

Upvotes: 7

StackedCrooked
StackedCrooked

Reputation: 35485

As mentioned by @Brian, your code does work on GCC 4.9.

I found that on GCC 4.8 you can make it work by wrapping the expansion in brackets:

const std::size_t    rank = (sizeof...(Sizes)); // OK

Upvotes: 2

Related Questions