Does a Declaration Using "Auto" Match an Extern Declaration That Uses a Concrete Type Specifier

Does a declaration using auto match an extern declaration that uses a concrete type specifier?

There's surprisingly little in the standard about this. About all we hear about redeclaration is:

[C++11: 3.1/1]: A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations. [..]

and the only relevant part of auto's semantics:

[C++11: 7.1.6.4/3]: Otherwise, the type of the variable is deduced from its initializer. [..]

(reminding us that the type of x is int).

We know that a variable must be given the same type by all declarations:

[C++11: 3.5/10]: After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given variable or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic.

and the "after all adjustments of types" ought to take care of any questions regarding auto's participation in all of this; my interpretation, then, is that this is inherently a valid redeclaration (and definition) of the x at global scope with type int, and that Clang is correct. Even if we propose that auto does not count as "adjustment of type", since no diagnostic is required, at worst all listed implementations are compliant in their own way.

I believe GCC and Visual Studio are taking the following as inspiration:

[C++11: 7.1.6.4/5]: A program that uses auto in a context not explicitly allowed in this section is ill-formed.

…but I think that this is short-sighted. It seems unlikely that the standard language is intended to prohibit the usual redeclaration rules, just because they are not repeated or explicitly referenced from within 7.1.6.4.

C++14 adds wording that relates to declarations of functions with deduced types:

[C++14: 7.1.6.4/13]: Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type. [..]

By symmetry one might suggest that, in your int case, it is intended that GCC and VS be correct in rejecting the program. However, this is a different feature (since deduction cannot be applied to mere declarations) and thus a different scenario.

Either way, improved standard wording would help here. I consider it a [reasonably minor] editorial defect.

Is it well-formed, if I redefine a variable as auto, and the deduced type is the same?

Tl;DR;

clang is correct, the logic is that this is allowed by [dcl.spec.auto] and to restrict this for deduced return types [dcl.spec.auto]p11 was added otherwise there is no restriction and therefore this is not restricted for the variables case.

See my more complete answer in the duplicate

Is auto(x); considered a declaration of a variable named x or an explicit type cast in C++23

Note the code referenced by the GCC bug in question:

int main() {
int x = 0;
float t;
t = auto(x);
}

auto(x) here is not a statement; it is unequivocally an expression. If auto(x) is used as an expression, it will behave as an expression. If it however is used in a way that makes it a statement, then it will behave as such.

Can global auto variables be declared in h files?

Is there any way to define a global auto variable in the source file and include it in some header file?

You cannot declare auto variable without initialisation. With auto, the type is deduced from the initialiser. Without initialiser, the compiler cannot know the type. The compiler needs to know what the type is.

If you instead use the deduced type in the header, then following is technically allowed (according to SO post linked in the other answer) although it mostly defeats the purpose of using auto:

// header
extern int a;

// cpp
auto a = 5;

But unfortunately in practice, some compilers don't like this.

As a working alternative, you could simply use an inline variable:

// header
inline auto a = 5;

Pre-C++17, you'll need to give up the dream of auto for extern variables.

Type deducted of method definition doesn't match declaration

You can simplify all that code to this:

struct A {
int func();
};

auto A::func() { return 0; }

This is not valid, a function that is declared with a placeholder type must use the placeholder in all declarations:

[decl.spec.auto]/13:

Redeclarations or specializations of a function or function template with a declared return type that uses a placeholder type shall also use that placeholder, not a deduced type.



Related Topics



Leave a reply



Submit