#include <iostream>
using namespace std;
struct test
{
test(){cout<<"class"<<endl;}
};
void test(){cout<<"function"<<endl;}
int main()
{
test();
return 0;
}
Output:
function
(VS2013 ang gcc 4.8.1)
Why function is selected? Isn't it ambiguity?
This is called name hiding and described in
3.3 Scope [basic.scope]
3.3.1 Declarative regions and scopes [basic.scope.declarative]
4) Given a set of declarations in a single declarative region, each of
which specifies the same unqualified name, — they shall all refer to
the same entity, or all refer to functions and function templates; or
— exactly one declaration shall declare a class name or enumeration
name that is not a typedef name and the other declarations shall all
refer to the same variable or enumerator, or all refer to functions
and function templates; in this case the class name or enumeration
name is hidden (3.3.10). [...]
emphasis mine.
Note that changing the order of declaration doesn't affect the outcome:
void test(){cout<<"function"<<endl;}
struct test
{
test(){cout<<"class"<<endl;}
};
int main()
{
test();
return 0;
}
still prints out function.
In case it isn't obvious, don't do this :)
From N3485 §3.3.10 [basic.scope.hiding]/2:
A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member,
function, or enumerator declared in the same scope.
Therefore, the function takes precedence over the class.
As mentioned in the comments, the class is still accessible via the class or struct keyword. If the class took precedence, the function would be unreachable.
I'm not certain either of the previous responses are the "why" for your particular instance.
Don't get me wrong; They are true and accurate.
I just think it's simpler.
In your example, you never instantiate the struct.
In other words, you declared it, but you never used it.
Since you never referenced it, it is never called.
Name precedence and such don't really apply here, since you never instantiated the struct.
Hope this helps,
-john
Related
I have the following simplified code
namespace Namespace
{
int foo() { return 1; }
class Class
{
public:
int foo() const { return 2; }
class Nested {
public:
Nested()
{
cout << foo() << endl;
}
};
};
}
And I got this error:
error: cannot call member function ‘int Namespace::Class::foo() const’
without object:
cout << foo() << endl;
^^^^^
It seems that compiler selects non static int Namespace::Class::foo() const instead of global function int Namespace::foo().
But how can it be expected that non-static function from other class can be called without object? Nested object has no access to surrounding Class object - this is not Java after all.
I read carefully through overload resolution from cppreference I cannot find the rationale for this behavior. I rather doubt that this is gcc error.
Can you point the language rules responsible for this behavior?
And how do you deal with such problems?
[UPDATE]
Just an answer for 2nd question. Workaround is simple, there is a need to tell compiler that such global function exists:
Nested()
{
using Namespace::foo; //< workaround: inform compiler such function exists
cout << foo() << endl;
}
BTW, is that workaround correct? Are there any better solutions?
I read carefully through overload resolution from cppreference I cannot find the rationale for this behavior. Can you point the language rules responsible for this behavior?
Before the overload resolution procedure selects the best viable function, an initial set of candidates is generated during the name lookup phase. In other words, the expected behavior should be searched for in the Name lookup section, not in the Overload resolution one.
The name lookup procedure for an unqualified name is described in the C++ standard:
§3.4.1 [basic.lookup.unqual]/p8:
A name used in the definition of a member function (9.3) of class X following the function’s declarator-id or in the brace-or-equal-initializer of a non-static data member (9.2) of class X shall be declared in one of the following ways:
— before its use in the block in which it is used or in an enclosing block (6.3), or
— shall be a member of class X or be a member of a base class of X (10.2), or
— if X is a nested class of class Y (9.7), shall be a member of Y, or shall be a member of a base class of Y
(this lookup applies in turn to Y’s enclosing classes, starting with the innermost enclosing class), or [...]
and only if still not found:
— if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class or a nested class within a local class of a function that is a member of N, before the use of the name, in namespace N or in one of N's enclosing namespaces.
Since the name lookup ends as soon as the name is found (§3.4.1 [basic.lookup.unqual]/p1):
In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name.
in your case no other scopes are searched as soon as int foo() const { return 2; } is encountered.
Workaround is simple, there is a need to tell compiler that such global function exists:
using Namespace::foo; //< workaround: inform compiler such function exists
Is that workaround correct?
§7.3.3 [namespace.udecl]/p1:
A using-declaration introduces a name into the declarative region in which the using-declaration appears.
§3.3.1 [basic.scope.declarative]/p1:
Every name is introduced in some portion of program text called a declarative region, which is the largest part of the program in which that name is valid, that is, in which that name may be used as an unqualified name to refer to the same entity.
Introducing a name with a using-declaration impacts the unqualified name lookup in a way such that it finds that function in its first step, namely that name becomes declared:
— before its use in the block in which it is used or in an enclosing block (6.3)
Are there any better solutions?
One can use a qualified name when referring to a function from some namespace scope, explicitly indicating what symbol is being referred to:
Nested()
{
cout << Namespace::foo() << endl;
}
This was indeed about Name Lookup and not about Overload Resolution.
Indeed, as the standard stipulates, §3.4.1/1 of N3376 (emphasis mine):
In all the cases listed in 3.4.1, the scopes are searched for a declaration in the order listed in each of the respective categories; name lookup ends as soon as a declaration is found for the name. If no declaration is found, the program is ill-formed.
So in fact, the lookup stops as soon as a declaration is found.
Then, you can find more about the case you're dealing with in §3.4.1/8 which deals with names used in class inside a member function definition, especially this part:
if X is a nested class of class Y (9.7), shall be a member of Y, or shall be a member of a base class of Y (this lookup applies in turn to Y’s enclosing classes, starting with the innermost enclosing class)
And if not found, in enclosing namespaces.
In your case, that means that Namespace::Class::foo() is the first name found during the lookup, and it stops as soon as it has found a name, so Namespace::foo() isn't even considered.
The example given by the standard illustrates the lookup path:
class B { };
namespace M {
namespace N {
class X : public B {
void f();
};
}
}
void M::N::X::f() {
i = 16;
}
The following scopes are searched for a declaration of i:
1) outermost block scope of M::N::X::f, before the use of i // 2) scope of class M::N::X
3) scope of M::N::X’s base class B
4) scope of namespace M::N
5) scope of namespace M
6) global scope, before the definition of M::N::X::f
And as to how you deal with such problem, you have to qualify the call, i.e.
cout << Namespace::foo() << endl;
so that the compiler selects the function you want through qualified lookup.
Piotr S. and JBL explained the why of your problem.
IMHO the simpler solution is to use the qualified name of the function :
public:
Nested()
{
cout << Namespace::foo() << endl;
}
I recently had the problem that I needed some helper functions to return instances of different types, similar to std::make_pair. My syntax of choice for this was:
Event event(Trigger(...), []() { });
where ... was some simple parameter that created a different trigger type based on ...'s type (e.g., Time, UserInput, etc.).
In addition I wanted some predefined triggers that could be used directly, such as:
Event event(Trigger::OnInit, []() { });
I found that defining a class and instance named Trigger allowed me to support both syntaxes:
static const struct Trigger {
static const OnceTrigger OnInit;
TimeTrigger operator()(Time const &) const;
UserTrigger operator()(UserInput const &) const;
} Trigger;
Notice the identically named type and instance names.
This works in both GCC and MSVC, but I am wondering if and how valid this is according to the standard. Is it "luck" that both compilers support this? Or is name lookup defined such that this is guaranteed to work on all compilers?
In the function call syntax Trigger(...), the class is hidden by the instance per 3.3.10:
2 - A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.
In the qualified name lookup syntax Trigger::OnInit, the class is visible per 3.4.3:
1 - [...] lookup of the name preceding [the] :: considers only namespaces, types, and templates whose specializations are types.
Indeed, the standard has an example which demonstrates how qualified name lookup is not subject to hiding of type names:
class A {
public:
static int n;
};
int main() {
int A;
A::n = 42; // OK
A b; // ill-formed: A does not name a type
}
So your code is fine per the standard. (Whether it's a good style is another matter entirely!)
Being able to name a structure (or class in C++) type the same as an instance of that structure is brought in from C, and it's because structure-names are in a separate namespace (not in the sense of C++ namespace though) compared to variable-names.
I'm working on a source editor for C++ and came up with simple optimization that I do not need to invalidate (e.g. highlighting, rebuild AST, do static analysis) the code before the currently edited statement (basically, before the previous semicolon/closing brace) but I am not sure if this is always true for C++.
E.g. in Java it is possible to call functions declared/defined after the edit location. Hence, if the user adds an argument to the function then error marker should be placed in the code before the edit location. In C++ function should be declared before it is used (and if the declaration does not match definition the error will be on definition).
Member function bodies defined inline in the class will be conceptually (and actually, in the compilers I know) parsed at the end of the class and can thus access members of the class declared after them.
Templates are compiled in two phases. The first phase is where they're defined, the second where they're instantiated. The current compilers can blame you for template errors at the point of instantiation, when substituting the actual arguments leads to an error in the template.
It would be entirely reasonable for your editor to follow the same logic. If the template definition looks good when you see it, it passes the first phase. When the code being edited instantiates a template, re-check, and blame any errors in the second phase on the instantiation.
This hints at a more fundamental problem. Where do you say an error occurred? The C++ standard doesn't care. As far as it's concerned, "syntax error somewhere" is a sufficient diagnostic. So, if there's an inline method trying to access a non-existing member this->a, you can claim there's an error in the method. But with equal validity, you can claim at the final }; that the class failed to define the necessary member a.
The underlying cause of all these errors is that two pieces of code must agree on something. When they don't, you can choose who to blame. For your editor, you could blame the fragment which came last. It's just a matter of getting the diagnostic wording right.
In general, outside a template definition, the rules for name lookup in C++ require a name to be declared before the point at which it is used. Your idea would therefore work in most cases. Unfortunately - as pointed out by SebastianRedl - there is a special case in which this rule of thumb does not apply.
Within a class definition, the declarations of all members of the class (and its enclosing class(es)) are visible during name lookup within the body of a member function (including a ctor-initializer-list or exception-specification), or in a default argument of a member function.
An illustration:
struct A
{
struct B
{
static void f(int i = M()) // uses 'A::M' declared later
{
A::f(); // calls A::f(int) declared later
}
};
static void f(void*)
{
f(); // calls A::f(int) declared later
}
static void f(int i = M()) // uses 'M' declared later
{
}
typedef int M;
};
If the token that was modified occurs within a member function-body or a default argument, you would have to reparse all classes that enclose the token.
From C++ Working Draft Standard N3337:
3.4.1 Unqualified name lookup [basic.lookup.unqual]
A name used in the definition of a member function (9.3) of class X following the function’s declarator-id
or in the brace-or-equal-initializer of a non-static data member (9.2) of class X shall be declared in one of
the following ways:
— before its use in the block in which it is used or in an enclosing block (6.3), or
— shall be a member of class X or be a member of a base class of X (10.2), or
— if X is a nested class of class Y (9.7), shall be a member of Y, or shall be a member of a base class of Y
(this lookup applies in turn to Y’s enclosing classes, starting with the innermost enclosing class), or
— if X is a local class (9.8) or is a nested class of a local class, before the definition of class X in a block
enclosing the definition of class X, or
— if X is a member of namespace N, or is a nested class of a class that is a member of N, or is a local class
or a nested class within a local class of a function that is a member of N, before the use of the name,
in namespace N or in one of N ’s enclosing namespaces.
$10.2/4- "[ Note: Looking up a name in
an elaborated-type-specifier (3.4.4)
or base-specifier (Clause 10), for
instance, ignores all nontype
declarations, while looking up a name
in a nested-name-specifier (3.4.3)
ignores function, variable, and
enumerator declarations."
I have found this statement to be very confusing in this section while describing about name lookup.
void S(){}
struct S{
S(){cout << 1;}
void f(){}
static const int x = 0;
};
int main(){
struct S *p = new struct ::S; // here ::S refers to type
p->::S::f();
S::x; // base specifier, ignores the function declaration 'S'
::S(); // nested name specifier, ignores the struct declaration 'S'.
delete p;
}
My questions:
Is my understanding of the rules correct?
Why ::S on the line doing new treated automatically to mean struct S, whereas in the last line ::S means the functions S in the global namespace.
Does this point to an ambiguity in the documentation, or is it yet another day for me to stay away from C++ Standard document?
Q1: I think so.
Q2: Compatibility with C. When you declare a struct in C, the tag name is just that, a tag name. To be able to use it in a standalone way, you need a typedef. In C++ you don't need the typedef, that makes live easier. But C++ rules have been complicated by the need to be able to import already existing C headers which "overloaded" the tag name with a function name. The canonical example of that is the Unix stat() function which uses a struct stat* as argument.
Q3: Standard reading is usually quite difficult... you need to already know that there is no place elsewhere modifying what you are reading. It isn't strange that people knowing how to do that are language lawyer...
You are mistaken about the second comment. In S::x, the S is a name in a nested name specifier. What the Standard refers to with "base-specifier" is the following
namespace B { struct X { }; void X() }
struct A : B::X { }; // B::X is a base-specifier
You are also not correct about this:
::S(); // nested name specifier, ignores the struct declaration 'S'.`
That code calls the function not because ::S would be a nested-name-specifier (it isn't a nested-name-specifier!), but because function names hide class or enumeration names if both the function and the class/enumeration are declared in the same scope.
FWIW, the following code would be equally valid for line 2 of your main
p->S::f();
What's important is that S preceedes a ::, which makes lookup ignore the function. That you put :: before S has no effect in your case.
According to the C++ Standard, function parameter's name is parsed by a declarator-id, and a declarator-id can also be a qualified name. That means, the following code is perfectly valid (if I've understood the relevant sections from the Standard correctly):
template<class T>
struct Sample
{
int fun(int T::count); //T::count is qualified variable name
};
My question basically is, why would anyone write such code? In what situations, the use of qualified name (in function parameter-list) can be advantageous?
EDIT:
It seems I understood the sections incorrectly. Instead of the above code, we can probably write the following code (as per the C++ standard):
template<class T>
struct sample
{
void fun(int arr[T::count]);
};
gcc-4.3.4 compiles it perfectly. But then, I'm not totally satisfied, because T::count is not a parameter anymore (I guess).
It's invalid. The syntax allows arbitrary declarators, but 8.3.5p8 says
An identifier can optionally be
provided as a parameter name; if
present in a function definition
(8.4), it names a parameter (sometimes
called “formal argument”)
Edit Another quote which syntactically constraints declarators (8.3p1, [dcl.meaning]):
Each declarator contains exactly one
declarator-id; it names the identifier
that is declared. The id-expression of
a declarator-id shall be a simple
identifier except for the declaration
of some special functions (12.3, 12.4,
13.5) and for the declaration of template specializations or partial
specializations (14.7). A declarator-id
shall not be qualified except for the
definition of a member function (9.3)
or static data member (9.4) or nested
class (9.7) outside of its class, the
definition or explicit instantiation
of a function, variable or class
member of a namespace outside of its
namespace, or the definition of a
previously declared explicit
specialization outside of its
namespace, or the declaration of a
friend function that is a member of
another class or namespace (11.4).
So in a parameter declaration, you must not use qualified names.
Edit: In the edited form, the function parameter type decays to an int*, even before a test is being made whether T::count actually exists and is an integer constant. If you want an example where a qualified name in such a signature would do something meaningful, consider
template<class T>
struct sample
{
void fun(int S=T::count);
};
When fun gets called without parameter, the compiler needs to determine the default argument, which then fails if T does not have a count member, or that cannot be converted to int.
As far as I understand your code is ill formed because
$8.3/1 : When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers, and the member shall not have been introduced by a using-declaration in the scope of the class or namespace nominated by the nested-name-specifier of the declarator-id. [Note: if the qualifier is the global ::scope resolution operator, the declarator-id refers to a name declared in the global namespace scope. ]
P.S: I am not 100% sure. Please correct me if I am wrong. :)
In what situations, the use of qualified name (in function parameter-list) can be advantageous?
Read Items 31 and 32 from Exceptional C++ by Herb Sutter. Both the items deal with Koenig lookup and the Interface principle.
It seems I understood the sections incorrectly. Instead of that code, we can probably write the following code (as per the C++ standard):
template<class T>
struct sample
{
void fun(int arr[T::count]);
};
gcc-4.3.4 compiles it perfectly. But then, I'm not totally satisfied, because T::count is not a parameter anymore (I guess).