Title
using-declarations in multiple-declaration contexts
Status
drwp
Section
9.9 [namespace.udecl]
Submitter
Andrew Koenig

Created on 1998-08-20.00:00:00 last changed 16 months ago

Messages

Date: 2005-01-15.00:00:00

Additional notes (January, 2005):

Some related issues have been raised concerning the following example (modified from a C++ validation suite test):

    struct A
    {
        int i;
        static int j;
    };

    struct B : A { };
    struct C : A { };

    struct D : virtual B, virtual C
    {
        using B::i;
        using C::i;
        using B::j;
        using C::j;
    };

Currently, it appears that the using-declarations of i are ill-formed, on the basis of 9.9 [namespace.udecl] paragraph 10:

Since a using-declaration is a declaration, the restrictions on declarations of the same name in the same declarative region (6.4 [basic.scope]) also apply to using-declarations.

Because the using-declarations of i refer to different objects, declaring them in the same scope is not permitted under 6.4 [basic.scope]. It might, however, be preferable to treat this case as many other ambiguities are: allow the declaration but make the program ill-formed if a name reference resolves to the ambiguous declarations.

The status of the using-declarations of j, however, is less clear. They both declare the same entity and thus do not violate the rules of 6.4 [basic.scope]. This might (or might not) violate the restrictions of 11.4 [class.mem] paragraph 1:

Except when used to declare friends (11.8.4 [class.friend]) or to introduce the name of a member of a base class into a derived class (9.9 [namespace.udecl], _N3225_.11.3 [class.access.dcl]), member-declarations declare members of the class, and each such member-declaration shall declare at least one member name of the class. 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.

Do the using-declarations of j repeatedly declare the same member? Or is the preceding sentence an indication that a using-declaration is not a declaration of a member?

Date: 2000-04-15.00:00:00

Notes from 04/00 meeting:

The core language working group was unable to come to consensus over what kind of declaration a using-declaration should emulate. In a straw poll, 7 members favored allowing using-declarations wherever a non-definition declaration could appear, while 4 preferred to allow multiple using-declarations only in namespace scope (the rationale being that the permission for multiple using-declarations is primarily to support its use in multiple header files, which are seldom included anywhere other than namespace scope). John Spicer pointed out that friend declarations can appear multiple times in class scope and asked if using-declarations would have the same property under the "like a declaration" resolution.

As a result of the lack of agreement, the issue was returned to "open" status.

See also issues 56, 85, and 138..

Date: 1999-04-15.00:00:00

Proposed Resolution (04/99): Change the comment "// error: double declaration" to "// OK: double declaration". (This should be reviewed against existing practice.)

Date: 2020-11-15.00:00:00

[Accepted at the November, 2020 meeting as part of paper P1787R6 and moved to DR at the February, 2021 meeting.]

Section 9.9 [namespace.udecl] paragraph 8 says:

A using-declaration is a declaration and can therefore be used repeatedly where (and only where) multiple declarations are allowed.
It contains the following example:
    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
    }
However, if "using A::i;" is really a declaration, and not a definition, it is far from clear that repeating it should be an error in either context. Consider:
    namespace A {
            int i;
            void g();
    }

    void f() {
            using A::g;
            using A::g;
    }
Surely the definition of f should be analogous to
    void f() {
            void g();
            void g();
    }
which is well-formed because "void g();" is a declaration and not a definition.

Indeed, if the double using-declaration for A::i is prohibited in f, why should it be allowed in namespace A1?

History
Date User Action Args
2021-02-24 00:00:00adminsetstatus: accepted -> drwp
2020-12-15 00:00:00adminsetstatus: open -> accepted
2005-01-14 00:00:00adminsetmessages: + msg1116
2000-05-21 00:00:00adminsetmessages: + msg355
2000-05-21 00:00:00adminsetstatus: review -> open
1999-09-14 00:00:00adminsetmessages: + msg89
1999-09-14 00:00:00adminsetstatus: drafting -> review
1998-08-20 00:00:00admincreate