Hector
Hector

Reputation: 2534

Multiple Declarations in C++

In [basic.scope.declarative]p4, one reads

Given a set of declarations in a single declarative region, each of which specifies the same unqualified name, — (4.1) they shall all refer to the same entity …

A naïve reading might imply that the following code might be valid because "both declarations refer to the same entity":

int x;
int x;

One then might remember the one definition rule [basic.def.odr]p1. The above reasoning might apply only to declarations not to definitions. The distinction is spelled out in [basic.def]p2. For example, the following code is certainly valid:

extern int x;
extern int x;

The last example in [basic.def]p2 suggests then that the following code should be valid, but it does not compile (using MSVC2015).

struct B
{
    int y;
};

struct D : B
{
    using B::y;
    using B::y;
};

Where is the problem?


The error message is

the using-declaration for 'B::y' cannot co-exist with the existing using-declaration for 'B::y'

Upvotes: 4

Views: 3168

Answers (2)

Arne Vogel
Arne Vogel

Reputation: 6666

You almost answered your own question by citing namespace.udecl/10. The example underneath (N3936) shows a location where multiple equivalent using-declarations are allowed:

namespace A {
    int i;
}
namespace A1 {
    using A::i;
    using A::i; // OK: double declaration
}
void f() {
    using A::i;
    using A::i; // error: double declaration
}
struct B {
    int i;
};
struct X : B {
    using B::i;
    using B::i; // error: double member declaration
};

Multiple using-declarations for a function are also allowed, at namespace and block scope. As to why they are not allowed for variables (objects) at block scope, I have no idea. Multiple equivalent member declarations are probably disallowed for two reasons:

  • large potential for initialization order bugs
  • it wasn't necessary historically, because the bodies of methods defined inline "see" members declared later in the same class (with the introduction of decltype in C++11, this reason is no longer as definitive)

Upvotes: 0

Anthony
Anthony

Reputation: 12387

This example from [namespace.udecl]p10 is exactly the same as yours:

struct B {
   int i;
};
struct X : B {
   using B::i;
   using B::i; // error: double member declaration
};

The error is backed up by [class.mem]p1:

A member shall not be declared twice in the member-specification, except that a nested class or member class template can be declared and then later defined, and except that an enumeration can be introduced with an opaque-enum-declaration and later redeclared with an enum-specifier.

So you're on the right track. Multiple declarations are OK, as long as they don't break other rules (e.g. one definition, member specifications etc.)

The following, for example, is fine:

struct X;
struct X;

Or a more complex example:

struct X 
{
    struct A;
    struct A
    {
       int y;
    };
}; 

struct X;
struct X::A;

Upvotes: 5

Related Questions