3

Why do I get the following error

$ g++ -std=c++11 aaa.cpp 

aaa.cpp:15:2: error: too many initializers for ‘const aaaa::Fruit_List [0]’

};

^

when compiling the following code:

class aaaa
{  // without wrapping in class the code compiles fine
    const int a=7; // compiles fine

    struct Fruit_List{
        int index;
        int length;
    } const fruit_list[]={ // error: if I put 5 in braket the code compiles fine
        {0,3},
        {1,2},
        {2,5},
        {3,1},
        {4,7}
    };
};

int main()
{
    return 0;
}

If I write the code without wrapping in the class, it would compile fine. Giving the length of the array will suppress compiler error. But insist of putting the code inside the class and avoid giving the array size as I may add any member later and I want to leave the array length determination to the compiler.

Strongly, please avoid linking to any inappropriate question.

Update

Thanks to juanchopanza's comment. Now I know that even this simpler code does not compile:

class aaaa
{
    const int a[]={7,4,5};
};

int main()
{
    return 0;
}
barej
  • 1,330
  • 3
  • 25
  • 56
  • 1
    C++ doesn't allow data members of type `T[]`. You need `T[N]` where `N` is a constant expression. Are you asking why it isn't allowed, or are you just after quotes from the standard that confirm it isn't? – juanchopanza Jan 24 '15 at 08:57
  • @fredrik sorry of ambiguity. i fixed it. – barej Jan 24 '15 at 08:58
  • Even if you remove `const`, it still gives an error. – shauryachats Jan 24 '15 at 09:00
  • @juanchopanza previously i used the code like `int a[]={1,2,3,4,5}` a lot. Do you mean this type of coding is now forbidden in C++? or mean that here is not the case I can enjoy leaving array length to the compiler? – barej Jan 24 '15 at 09:02
  • 1
    No, I said "C++ doesn't allow **data members** of type T[]. I guess `a` is not a data member. In a class, you can have `T = {....}` or `T{.....}` where `T` is a complete type. `Q[]` doesn't satisfy that. – juanchopanza Jan 24 '15 at 09:03
  • What juanchopanza is saying is that "it makes a difference that `fruit_list` is inside a class, vs. inside a function". If it is inside a class, it needs to have a constant size. – Mats Petersson Jan 24 '15 at 09:11
  • How about linking to a [relevant question](http://stackoverflow.com/questions/21152171/too-many-initializers-for-int-0-c) and the relevant comments from [Stroustrup](http://www.stroustrup.com/C++11FAQ.html#member-init) himself? – dmg Jan 24 '15 at 09:14
  • @MatsPetersson, Now my question is that, why compiler is unable to find the array length. It does not seem to be hard for compiler. – barej Jan 24 '15 at 09:14
  • @dmg, :) At the time of posting question i searched a lot. But thought it is related to the array of structure! – barej Jan 24 '15 at 09:15
  • It is not UNABLE to, it is NOT ALLOWED according to the standard. (The error message could be clearer, but the error is not that the compiler "can't count", but "you didn't write a size in the array") – Mats Petersson Jan 24 '15 at 09:17
  • How come it is allowed in a function but not in a class? Does it have any philosophy? – barej Jan 24 '15 at 09:18
  • @barej My best guess is that because in a function you are doing allocation. In the class description you are not. – dmg Jan 24 '15 at 09:21
  • 1
    That question you'd have to ask the C++ standards committee... ;) My guess is that it makes it hard to determine the size of the whole struct in a meaningfull way. What if you do: `class a { const int b[]; }; ... const int a::b = { 1,2,3,4,5 };` which I believe is allowed if there is a fixed size... What if the `a::b = ..` is in another file? – Mats Petersson Jan 24 '15 at 09:21
  • Thanks to all guys helping. The problem seems to be simpler that what I thought. @juanchopanza has mentioned the exact point. you may post your comment as the answer. – barej Jan 24 '15 at 09:24

1 Answers1

0

As you probably understand, by wrapping it into a class, your supposed constants are no longer names that refer to an object with a fixed value given at initializing the constant. Instead, you are now declaring constant data members, which are like non-constant data members, and exist in each instance in that class on their own. The value you provide is nothing more than a default value for initializing the constant member in the constructor.

Consider this example:

#include <ostream>
#include <iostream>

struct Demo {
  const int args[3];
  Demo() : args{1,2,3} {}
  Demo(int x) : args{x,x,x} {}
  Demo(int y, int z) : args{y, z} {}
};

int main(void)
{
  Demo d1;
  Demo d2(1,2);
  std::cout << d2.args[0] << ' ' << d2.args[1] << ' '
            << d2.args[2] << '\n';  // outputs "1 2 0"
  return 0;
}

Not all of the constructors initialize Demo::args with the same amount of values. This is valid, and the remaining elements are zero-filled. The initialization you provide in a class for non-static data member is just syntactic sugar for using that value in every constructor where no explicit value for that member is specified in the init list, so the example above could also be written this way:

#include <ostream>
#include <iostream>

struct Demo {
  const int args[3] = {1,2,3};
  Demo() {}
  Demo(int x) : args{x,x,x} {}
  Demo(int y, int z) : args{y, z} {}
};

int main(void)
{
  Demo d1;
  Demo d2(1,2);
  std::cout << d2.args[0] << ' ' << d2.args[1] << ' '
            << d2.args[2] << '\n';  // outputs "1 2 0"
  return 0;
}

The initializer at the member Demo::args is not the initializer, but just one initializer, while constructors may specify different ones. This is most likely why size deduction is not allowed, just like you can not use auto on non-static data members.

If you just meant to put the name of a single named entity with a constant value all the time while your program is running into the namespace provided by a class, but did not want to get the ability to specivy different values in some constructor, use a static constant inside the class.

Michael Karcher
  • 3,803
  • 1
  • 14
  • 25