What the declaration using directive declares?

48 megtekintés
Ugrás az első olvasatlan üzenetre

Vlad from Moscow

olvasatlan,
2015. okt. 11. 6:59:052015. 10. 11.
– ISO C++ Standard - Discussion
As the using directive is a declaration then I thought that it introduces a namespace name in the declarative region. For example

using namespace N1;

introduces name N1 as a namespace name in the global namespace.

However compilers issue an error if a using directive refers a name that was not yet defined as a namespace name before the using directive.

But if to write

using namespace std;

before any standard header (that is before the definition of the namespace std) then the corresponding code is compiled successfully.

So a question arises what the using directive declare?.

Shall compilers issue an error if a using directive refers a name of a namespace that is defined after the using directive?

Columbo

olvasatlan,
2015. okt. 11. 7:15:192015. 10. 11.
– ISO C++ Standard - Discussion
before any standard header (that is before the definition of the namespace std) then the corresponding code is compiled successfully.
Nope. 

Johannes Schaub

olvasatlan,
2015. okt. 11. 7:40:322015. 10. 11.
– std-dis...@isocpp.org
2015-10-11 12:59 GMT+02:00 Vlad from Moscow <vlad....@mail.ru>:
> As the using directive is a declaration then I thought that it introduces a
> namespace name in the declarative region. For example
>
> using namespace N1;
>
> introduces name N1 as a namespace name in the global namespace.
>
> However compilers issue an error if a using directive refers a name that was
> not yet defined as a namespace name before the using directive.
>
> But if to write
>
> using namespace std;
>
> before any standard header (that is before the definition of the namespace
> std) then the corresponding code is compiled successfully.
>

This is a known bug in some compilers. Probably caused by compiler
writers being too lazy to synthesize their global operator new without
compiler magic and without exposing namespace std. So in contradiction
to the spec, they bring std in scope.

Vlad from Moscow

olvasatlan,
2015. okt. 11. 8:06:102015. 10. 11.
– ISO C++ Standard - Discussion
But what about my original question?

In my opinion it would be logically consistent if the using directive declares a namespace. That is it introduces a name of a namespace in the given declarative region.

It does not declare any other names because only the namespace name is present in the declaration.

The names themselves declared in the referred namespace are used in  the name look up.  They are not declared by the using directive. They are declared in the corresponding namespace definition. And moreover the lookup itself taking into account the using directive differs depending on whether a quakified name or unqualified name is searched. And the names is considered as placed in different namespaces depending on the lookup. For example for unqualified name lookup the names look like they are placed in a enclosing namespace of two namespaces.

Thus  the using directive declares only the namespace that is used in the directive and nothing more. 

Vlad from Moscow

olvasatlan,
2015. okt. 11. 8:30:302015. 10. 11.
– ISO C++ Standard - Discussion
And according to the C++ Standard (3 Basic concepts)

5 Every name that denotes an entity is introduced by a declaration 

So the using directive is a declaration of the name that is specified in the directive. It is only a declaration of the namespace. On the other hand, construction

namespace N
{
}

is a declaration and at the same is a definition of the namespace N.

I am sure that compilers shall not issue any error for example for statement

using namespace A;

This directive is a declaration of name A as a namespace name.

They could issue an error for statement like this

using namespace A::B;

provided that name A was not yet declared as a namespace name either by using the using directive

using namespace A;

or by using a definition of the namespace like

namespace A
{
}

Vlad from Moscow

olvasatlan,
2015. okt. 11. 8:44:522015. 10. 11.
– ISO C++ Standard - Discussion
It shall be equivalent to the class declaration and the class definition. 

This

class A;

is a class declaration. It introduces  name A as a class name in the given declarative region.

This is

class A {};

is a class definition (and at the same time a class declaration). It not only introduces the name A but also defines other entities that compose the class.

The same shall be valid for namespaces.

using namesapec A;

is a declaration and

namespace A {}

is a namespace declaration and definition.

So if compilers issue an error for statement

using namespace A;

then it should be considered either as a compiler bug or as a Standard bug.

Thiago Macieira

olvasatlan,
2015. okt. 11. 11:20:322015. 10. 11.
– std-dis...@isocpp.org
On Sunday 11 October 2015 05:44:52 Vlad from Moscow wrote:
> This
>
> class A;
>
> is a class declaration. It introduces name A as a class name in the given
> declarative region.
>
> This is
>
> class A {};
>
> is a class definition (and at the same time a class declaration). It not
> only introduces the name A but also defines other entities that compose the
> class.
>
> The same shall be valid for namespaces.
>
> using namesapec A;

For symmetry, that would be:

namespace A;

> is a declaration and
>
> namespace A {}
>
> is a namespace declaration and definition.
>
> So if compilers issue an error for statement
>
> using namespace A;
>
> then it should be considered either as a compiler bug or as a Standard bug.

I don't see the need to change. What's the motivation?

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

Vlad from Moscow

olvasatlan,
2015. okt. 11. 11:49:452015. 10. 11.
– ISO C++ Standard - Discussion
Compilers behave differently when encounter a using directive with a namespace that was not yet defined. This confuses users.

It is not clear from the C++ Standard what exactly the using directive declares.

As for me the only correct answer that the using directive introduces a name denoting a namespace  in the scope. There is no need that the namespace would be already defined.

I am sure that this should be written in clear terms in the Standard.  Any declaration introduces a name of an entity used in the declaration.

In this case you could say that the compilers have bugs.

Johannes Schaub

olvasatlan,
2015. okt. 11. 11:57:022015. 10. 11.
– std-dis...@isocpp.org
> Compilers behave differently when encounter a using directive with a
> namespace that was not yet defined. This confuses users.
>
> It is not clear from the C++ Standard what exactly the using directive
> declares.
>

It declares nothing. Compilers also behave differently for `struct A {
int x; struct x { }; }; typename A::x y;` (with GCC accepting and
clang rejecting). I am sure you can find much more cases like that.
Why is there a need for change in the Standard just because a compiler
has a bug?

Columbo

olvasatlan,
2015. okt. 11. 11:57:542015. 10. 11.
– ISO C++ Standard - Discussion
Am Sonntag, 11. Oktober 2015 16:49:45 UTC+1 schrieb Vlad from Moscow:
Compilers behave differently when encounter a using directive with a namespace that was not yet defined. This confuses users.
Of course bugs confuse users.

It is not clear from the C++ Standard what exactly the using directive declares.
It declares nothing, which is absolutely clear from the standard. It solely changes the way in which unqualified names are treated. And it would be confusing to allow them to name non-yet-existent namespaces. 

Vlad from Moscow

olvasatlan,
2015. okt. 11. 12:18:032015. 10. 11.
– ISO C++ Standard - Discussion
Your words do not make sense.  They sound like "a declaration that declares nothing".:)

I suggest that the Standard had no such statements like "this declaration decalres nothing" (What is the "nothing" according to the Standard?)? or "this definition defines nothing".:)

So the using declaration indeed declares and it declares a name of a namespace.

Columbo

olvasatlan,
2015. okt. 11. 12:19:152015. 10. 11.
– ISO C++ Standard - Discussion
Am Sonntag, 11. Oktober 2015 16:57:02 UTC+1 schrieb Johannes Schaub:
It declares nothing. Compilers also behave differently for `struct A {
int x; struct x { }; }; typename A::x y;` (with GCC accepting and
clang rejecting).
Clang doesn't properly implement [class.member.lookup]/4 yet; I did file #24810 for that, but your simplified example makes me feel like there's a dup?

Vlad from Moscow

olvasatlan,
2015. okt. 11. 12:20:072015. 10. 11.
– ISO C++ Standard - Discussion
Take into account that otherwise you have to define clear in the Standard what is the empty declaration and what is the declaration that declares nothing.:) 

Columbo

olvasatlan,
2015. okt. 11. 12:26:312015. 10. 11.
– ISO C++ Standard - Discussion
A declaration does not have to declare an entity. A static_assert-declaration declares a "condition". A using-directive declares that unqualified names be treated accordingly. (One could argue that they don't declare anything whatsoever; [dcl.dcl] goes "Declarations generally specify how names are to be interpreted."). 
Az üzenetet töröltük.

Vlad from Moscow

olvasatlan,
2015. okt. 11. 12:39:012015. 10. 11.
– ISO C++ Standard - Discussion


On Sunday, October 11, 2015 at 7:26:31 PM UTC+3, Columbo wrote:
A declaration does not have to declare an entity. A static_assert-declaration declares a "condition". A using-directive declares that unqualified names be treated accordingly.


In my opinion this phrase  "A using-directive declares that unqualified names be treated accordingly." does not make any sense.

Take into account that using directive is also considered for qualified name lookup.

Miro Knejp

olvasatlan,
2015. okt. 11. 12:39:072015. 10. 11.
– std-dis...@isocpp.org
Do not confuse the *using directive* with the *using declaration*. Those are two very different things and you should be careful about using the correct terms.

Columbo

olvasatlan,
2015. okt. 11. 12:47:252015. 10. 11.
– ISO C++ Standard - Discussion
On Sunday, October 11, 2015 at 5:39:01 PM UTC+1, Vlad from Moscow wrote:
Take into account that using directive is also considered for qualified name lookup.
I was trying to keep things simple.

Miro Knejp

olvasatlan,
2015. okt. 11. 12:51:082015. 10. 11.
– std-dis...@isocpp.org
Am 11.10.2015 um 18:39 schrieb Vlad from Moscow:


On Sunday, October 11, 2015 at 7:26:31 PM UTC+3, Columbo wrote:
A declaration does not have to declare an entity. A static_assert-declaration declares a "condition". A using-directive declares that unqualified names be treated accordingly.


In my opinion this phrase  "A using-directive declares that unqualified names be treated accordingly." does not make any sense.
That is not a quote from the standard. See [namespace.udir]/3 "A using-directive does not add any members to the declarative region in which it appears."

There is a reason it is called "directive" and not "declaration". At no point in [namespace.udir] is it mentioned that the using directive declares anything, because it is *not a declaration*. It directs the compiler to adjust its name lookup algorithm.

Columbo

olvasatlan,
2015. okt. 11. 12:52:362015. 10. 11.
– ISO C++ Standard - Discussion
On Sunday, October 11, 2015 at 5:51:08 PM UTC+1, Miro Knejp wrote:
At no point in [namespace.udir] is it mentioned that the using directive declares anything, because it is *not a declaration*.
Well, technically speaking it is. 

Vlad from Moscow

olvasatlan,
2015. okt. 11. 12:59:482015. 10. 11.
– ISO C++ Standard - Discussion
According to the C++ Standard the using directive is a declaration. And moreover it is referred in section 3.1 Declarations and definitions as an example of a declaration that is not at the same time a definition. 

Johannes Schaub

olvasatlan,
2015. okt. 11. 13:03:532015. 10. 11.
– std-dis...@isocpp.org
My testcase is illformed because "A::x" refers to a data member (which
hides the class name) but typename must designate a type. GCC's lookup
is broken because it ignores non-type names, but typename must not
ignore non-type names.

Your PR seems to be invalid to me. The Standard is talking about name
lookup constraints, not arbitrary potential for ill-formedness when
deciding whether or not to find a declaration.

Miro Knejp

olvasatlan,
2015. okt. 11. 13:18:422015. 10. 11.
– std-dis...@isocpp.org
Yes, technically it is, but the correct term to refer to it is still *using directive* (7.3.4) because a *using declaration* (7.3.3) is something different, as is also listed in the paragraph you refer to.

Note also that [basic.def]/1 says "A declaration (Clause 7) may introduce one or more names into a translation unit or redeclare names introduced by previous declarations. (...) A declaration may also have effects". Note the use of "may". So a declaration can either (re)declare entities and/or declare an effect.

A using-directive does not intruduce new names into the translation unit nor does it redeclare existing ones, but it declares an effect: it changes how names are looked up in the current scope (which is why it cannot be put under empty-declaration).

Columbo

olvasatlan,
2015. okt. 11. 13:25:022015. 10. 11.
– ISO C++ Standard - Discussion
Your PR seems to be invalid to me. The Standard is talking about name
lookup constraints, not arbitrary potential for ill-formedness when
deciding whether or not to find a declaration.
Oh, okay. I misinterpreted that paragraph, thanks for clarifying.

Vlad from Moscow

olvasatlan,
2015. okt. 11. 13:37:082015. 10. 11.
– ISO C++ Standard - Discussion
If to agree with you then in this case I do not see a sense to refer the using derictive in section 3.1 Declarations and definitions. because it does not declare as you are saying anything and it does not define anything. It simply has some "effect". So at least it should be stated clearly in this section. Otherwise it only confuses readers.

So in any case the Standard has a defect.

In my opinion the best approach is to adopt that the using directive introduces a name of a namespace in the declarative region.

Miro Knejp

olvasatlan,
2015. okt. 11. 13:49:182015. 10. 11.
– std-dis...@isocpp.org
No, I wrote "So a declaration can either (re)declare entities and/or declare an effect."
You can declare an entity and you can declare an effect. There is nothing wrong with that statement in the English language and reflects what the using directive does.

Johannes Schaub

olvasatlan,
2015. okt. 11. 16:06:002015. 10. 11.
– std-dis...@isocpp.org

As an example where it makes a difference in otherwise valid code: https://llvm.org/bugs/show_bug.cgi?id=8263

Válasz mindenkinek
Válasz a szerzőnek
Továbbítás
0 új üzenet