Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Non-static member initialization of char array with brace gives an error in gcc while not in clang

Consider following code:

#include <iostream>

class A
{
    char name[40] = { "Blank" }; // note the braces here
public:
    const char *getName() { return name; }
};

int main()
{
    A a;

    std::cout << a.getName() << std::endl;
}

It gives an error in gcc (latest version 5.2.0):

prog.cpp:5:28: error: invalid conversion from 'const char*' to 'char' [-fpermissive]
  char name[40] = { "Blank" };
                            ^

But it's not the case for clang, that compiles it flawlessly with -std=c++11 -pedantic -Wall.

Is it really incorrect to put braces for non-static initializer here?

AFAIR it doesn't matter if braces are present or not. For instance, the definition of array, such as:

char text[] = "some text";

is equivalent to:

char text[] = { "some text" };
like image 428
Grzegorz Szpetkowski Avatar asked Jul 22 '15 09:07

Grzegorz Szpetkowski


3 Answers

The code is valid, and is now accepted by GCC trunk. I think it was fixed by PR 65815 brace elision doesn't work in NSDMI

like image 86
Jonathan Wakely Avatar answered Oct 19 '22 21:10

Jonathan Wakely


Well the standard is not very clear in my opinion, but I would say that CLang is right :

8.5.1 says :

§2 : When an aggregate is initialized by an initializer list, as specified in 8.5.4, the elements of the initializer list are taken as initializers for the members of the aggregate, in increasing subscript or member order. That is gcc interpretation : name is an array, there is a brace-init-list so first element of the array (a char) is initialized with the char array => error

But 8.5.2 explicitely says : An array of narrow character type ... can be initialized by a narrow string literal ... or by an appropriately-typed string literal enclosed in braces (emphasize mine)

My interpretation is that the standard consideres char arrays as special enough to explicitely allow a string literal enclosed in braces as valid even if it defeats 8.5.1 §2

like image 5
Serge Ballesta Avatar answered Oct 19 '22 19:10

Serge Ballesta


From the C++ standard working draft n4527 [dcl.init]. An initialization can be written like :

Initializers

initializer:
  brace-or-equal-initializer
  ( expression-list )

brace-or-equal-initializer:
  = initializer-clause
  braced-init-list

initializer-clause:
  assignment-expression
  braced-init-list
initializer-list:
  initializer-clause...opt
  initializer-list,initializer-clause...opt

braced-init-list:
  {initializer-list,opt}
  { }

A Class member declaration

member-declarator:
  declarator virt-specifier-seq opt pure-specifier opt
  declarator brace-or-equal-initializer opt

From what I read it seems like gcc does not meet the standard. Because the class member initialization using the braces is accepted by the standard.

like image 4
Pumkko Avatar answered Oct 19 '22 21:10

Pumkko