15
class Foo {
 public:
  static const char *constant_string;
};

auto Foo::constant_string = "foo";

int main(void) {
};

Compiled with: gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3 like this:

gcc -std=c++0x ./foo.cc 
./foo.cc:6:11: error: conflicting declaration ‘auto Foo::constant_string’
./foo.cc:3:22: error: ‘Foo::constant_string’ has a previous declaration as ‘const char* Foo::constant_string’
./foo.cc:6:11: error: declaration of ‘const char* Foo::constant_string’ outside of class is not definition [-fpermissive]

Is this intended behavior of the auto keyword, or a bug in gcc+

ildjarn
  • 62,044
  • 9
  • 127
  • 211
slacy
  • 11,397
  • 8
  • 56
  • 61
  • 1
    `"foo"` isn't really `const char*` but `const char[4]`. – Bo Persson Jan 11 '13 at 21:06
  • 1
    Not sure what you are trying to achieve here with auto. constant_string already is declared and static initialization should be ok without auto. – kchoi Jul 31 '15 at 14:54

2 Answers2

12

It's disallowed by the language:

[C++11: 7.1.6.4]:

1 The auto type-specifier signifies that the type of a variable being declared shall be deduced from its initializer or that a function declarator shall include a trailing-return-type.

2 The auto type-specifier may appear with a function declarator with a trailing-return-type (8.3.5) in any context where such a declarator is valid.

3 Otherwise, the type of the variable is deduced from its initializer. The name of the variable being declared shall not appear in the initializer expression. This use of auto is allowed when declaring variables in a block (6.3), in namespace scope (3.3.6), and in a for-init-statement (6.5.3). auto shall appear as one of the decl-specifiers in the decl-specifier-seq and the decl-specifier-seq shall be followed by one or more init-declarators, each of which shall have a non-empty initializer.

4 The auto type-specifier can also be used in declaring a variable in the condition of a selection statement (6.4) or an iteration statement (6.5), in the type-specifier-seq in the new-type-id or type-id of a new-expression (5.3.4), in a for-range-declaration, and in declaring a static data member with a brace-or-equal-initializer that appears within the member-specification of a class definition (9.4.2).

5 A program that uses auto in a context not explicitly allowed in this section is ill-formed.

It's hard to prove a negative, but there's simply no explicit rule in the standard to allow auto in your case.

However, the same rules mean that the following is valid:

struct Foo {
   static constexpr auto constant_string = "foo";
};

int main() {}

(Note that the type of Foo::constant_string is char const* const rather than, say, char const[3]; this is an effect of using auto.)

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
  • 5
    +1 The reason why is that this case would be awkward: `struct foo { static long x; }; auto foo::x = 0;` The initializer says the type should be `int`, but the declaration says it should be `long`. Should `auto` cast the initializer (something it does in no other context), should it fail to compile, or should `auto` reuse the existing type (and therefore serve little purpose but to relieve the programmer from typing), requiring more wording in the standard? I'm sure this came up and it was decided to do the simplest thing: ban it altogether. – GManNickG Jan 11 '13 at 19:36
  • @GManNickG: Agreed. Given this, I'm surprised there's no explicit mention, even if only in a _Note_. – Lightness Races in Orbit Jan 11 '13 at 19:38
  • -1, every definition is a declaration (in this case the definition is also a redeclaration as it declares the variable a second time). and paragraph 1 allows the example he gives (some of what appears in paragraph 4 appears to be redundant since it is allowed by paragraph 1 already). – Johannes Schaub - litb Jan 11 '13 at 19:55
  • @gman we have existing rules that say that every redeclaration shall specify the same type. the same scenario applies when you substitute the auto by int. the linkage rules render this case illformed with no diagnoatic required. – Johannes Schaub - litb Jan 11 '13 at 19:56
  • @JohannesSchaub-litb: I tried to find the language for "every definition is a declaration" so that I could find an exemption, but could not find any at all -- instead all I can find is the rules for "every declaration is a definition" for which there _is_ an exception for this case. So where is it given that the OP's `auto Foo::constant_string = "foo";` is also a declaration? Indeed this would seem counter-intuitive since it is incapable of adding the name `constant_string` into any scope without a pre-existing declaration inside the class definition. – Lightness Races in Orbit Jan 11 '13 at 19:58
  • @Lightness: 3.1p2 "A declaration is a _definition_ unless...". So "definition" is a subcategory of "declaration", and the following text describes the situations in which a declaration is not also a definition. The C++ grammar classifies many sequences of tokens as declarations, but has no syntactic classification for definitions - only the semantics from 3.1 says what a definition is. – aschepler Jan 11 '13 at 20:20
  • @aschepler: I don't buy that. Just because some declarations are also definitions does not mean that all definitions must also be declarations. I admit there's an implication there but it's hardly iron-clad. There must be some further wording in 7 to further tell us what a static member definition really _is_; certainly it's clear that it does not introduce a name, though not all declarations are required to. – Lightness Races in Orbit Jan 11 '13 at 20:22
  • 1
    Except that sentence is C++'s definition of the word "definition". You can tell because the word is italicized. – aschepler Jan 11 '13 at 20:24
  • @aschepler: Okay a further question for you, then: `we have existing rules that say that every redeclaration shall specify the same type` Is it standard-mandated that this means the type before `auto` is applied? `auto` is not even a type, and the OP's diagnostic demonstrates that `auto` was going to resolve to the same type held by the original declaration. – Lightness Races in Orbit Jan 11 '13 at 20:26
  • @LightnessRacesinOrbit: "the type before `auto` is applied" makes no sense. When `auto` is involved in a non-function declaration, the type of each declarator is determined from its initializer (independently of any previous declarations). If there was a previous declaration of the same variable with different type, error. – aschepler Jan 11 '13 at 20:33
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/22604/discussion-between-aschepler-and-lightness-races-in-orbit) – aschepler Jan 11 '13 at 20:44
  • Unfortunately the paragraphs you cited are two paragraphs from each other and the way you quoted them makes it sound that "the auto type-specifier can also be used" is intended to match with paragraph 1, thereby extending what paragraph 1 allows. But that's not the case: paragraph 4 comes after paragraph 3, and paragraph 3 does not allow all variable declarations to use "auto". Therefor, what I said in my downvote comment does not apply to the Standard's text. It just applies to your answer's quotes. I take it back: The Standard disallows this use of auto... – Johannes Schaub - litb Jan 11 '13 at 21:04
  • But I will only take back my downvote once you removed your incorrect statement that his definition is not a declaration. If a thing exists, it must be defined somewhere. And there is no definition for the term "definition" that defines a variable that is not also a declaration. For whether or not a declaration introduces a name, see 3.1p1: "... or redeclares names introduced by previous declarations.". – Johannes Schaub - litb Jan 11 '13 at 21:06
5

Visual C++ accepts

decltype(Foo::constant_string) Foo::constant_string = "foo";
Bruno Martinez
  • 2,850
  • 2
  • 39
  • 47