Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Declare the same identifier as const variable and member function

I have wrote the following piece of code

#include <iostream>
const int N = 5;
class X
{
  public:
  int array[N];
  void foo()
  {
     std::cout << "array size:"<<sizeof(array)/N << std::endl;   
  }
  enum
 {
   N = 3    
  };
};

int main()
{
  X x;
  x.foo();
} 

The aforementioned code does not compile with GCC:

<source>:13:8: error: declaration of 'N' [-fpermissive]
    N = 3
        ^
<source>:2:11: error: changes meaning of 'N' from 'const int N' [-fpermissive]
 const int N = 5;
           ^

From my point in compile time the array is defined as an array of five integers and N is defined as 5. How the compiler resolved the name declaration of variables?

like image 667
getsoubl Avatar asked Jan 01 '23 23:01

getsoubl


1 Answers

Inside the scope of member functions (even those defined inline), the class is considered complete1. As such, using N there must use the member enumerator. And its value must be 3.

But, that is not the case when declaring class member data. At that point (when specifying array), the class is not made to be considered complete. So N can only refer to what was seen previously, which means it must be the global constant.

Clang accepts it, but emits 6 (sizeof(int) * 5 / 3). GCC (8) doesn't, but it isn't really invalid code. It's just error prone. The way to make better defined would be to move the enumerator to before the array is defined

enum { N = 3 };
int array[N];

... or if we don't, then we can use scope resolution to refer to the "correct N"

sizeof(array) / ::N

Rearranging the class definition would be better, since it will not still remain error prone (we can forget to use the qualified ::N).


1: From the latest C++ standard draft

[class.mem]/6

A complete-class context of a class is a

  • function body ([dcl.fct.def.general]),
  • default argument ([dcl.fct.default]),
  • noexcept-specifier,
  • contract condition ([dcl.attr.contract]), or
  • default member initializer

within the member-specification of the class.

like image 111
StoryTeller - Unslander Monica Avatar answered Jan 05 '23 15:01

StoryTeller - Unslander Monica