Reputation: 2534
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
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:
decltype
in C++11, this reason is no longer as definitive)Upvotes: 0
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