I don't understand why the following code gives error:
namespace A
{
void f(double x){cout<<"A::f(double)\n";}
void f(string s){cout<<"A::f(string)\n";}
namespace B
{
using namespace A;
void f(int x){cout<<"B::f\n";}
void call()
{
f(10); // calls B::f, expected
f(10.5); // calls B::f, why??
string s="Hi";
f(s); // error, why??
}
}
}
My understanding was to search a name, compiler starts from current scope and continuously search enclosing scope and then global scope until it finds correct (correct means signature match or convertible in case of method) one, or gives error if none is present. So at first I tried without using namespace A in B. Then the first two call invoked B::f as expected, but f(s) was giving error. I thought names in enclosing scope are by default visible to inner scope, but clearly I was wrong. Then I place using namespace A and thought f(10.5) will call A::f for better type matching, and the problem with f(s) will be solved, but this is not the case (my understanding was using keyword bring everything to current scope from the scope which is being used). Can someone help me to understand how name lookup is applied here, thanks in advance.
Note
I know how to make it work. I wanted to know why this is so? what C++ standard says about this in easy to understand language. Why my understanding is wrong?
Since, you are not calling A::f(), these will happen:
f(10.5); // cast to int
string s="Hi";
f(s); //I do not know any B::f(), with string argument.
To be more exact, in the first line of the code I pasted,
the compiler will try to call f(int a). You pass 10.5 and the function waits for an integer. However, 10.5 can be casted to an int, by cutting its decimal digits. This function is the one of namespace B.
[EDIT]
The default namespace is the one you have your functions inside. In order to not the use the default, you have to specify it yourself, be the :: operator.
If you remove the f() inside the namespace B, then the compiler will go to the namespace A, which is the 'outer' namespace.
Maybe this analogy with the scope of the variables can help.
int main() {
int a = 10;
{
int a = 5;
std::cout << a << std::endl;
}
return 0;
}
The output is 5. When it's time to print a, the compiler will go and find the last declared a, except otherwise told by us.
This is what is known as name hiding:
A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (10.2).
The declaration of B::f is hiding both overloads of A::f despite the using namespace declaration. The technical reason for which it wasn't working was because of the way unqualified lookup works. The compiler first searches the most local namespace for the symbol, and works its way up until it finds it. Implicit conversions are allowed which was why B::f was consistently being called and why the overload for std::string could not be chosen. To fix this, you can add the outer namespace function in explicitly using a using declaration:
using A::f;
void f(int) { ... }
void call()
{
// ...
}
Here is a demo.
That to understand the compiler behaviour it is important to reference to the following quote from the C++ Standard
2 A using-directive specifies that the names in the nominated
namespace can be used in the scope in which the using-directive
appears after the using-directive. During unqualified name lookup
(3.4.1), the names appear as if they were declared in the nearest
enclosing namespace which contains both the using-directive and the
nominated namespace. [ Note: In this context, “contains” means
“contains directly or indirectly”. —end note ]
In your example "the nearest enclosing namespace which contains both the using-directive and the
nominated namespace." is namespace A. That is functions
void f(double x){cout<<"A::f(double)\n";}
void f(string s){cout<<"A::f(string)\n";}
are not members of namespace B for the purpose of the unqualified lookup.
Accotding to other quote from the C++ Standard
1 A name can be hidden by an explicit declaration of that same name in
a nested declarative region or derived class (10.2).
these function declarations are hidden by the explicit declaration of f in namespace B. So the compiler found name f in namespace B and it stopped the further search of the name.
You are running into something called implicit conversion. Check out this page, or another one.
As pointed out in other answer, only the current scope is explored by the compiler, and he tries to convert the given argument to the one expected, and fails if he can't.
Related
I'm getting a "too few arguments in function call" while trying to call a function from another namespace that happens to have the same name with the function it's being called from. Here, you can see what I mean:
namespace doa::texture {
using namespace internal::texture;
Texture* const CreateTexture(const std::string& name, const std::string& pathToTextureImage) {
//below should call internal::texture::CreateTexture, not doa::texture::CreateTexture
Texture* texture{ CreateTexture(pathToTextureImage) };
... //implementation detail
}
}
namespace internal::texture {
Texture* const CreateTexture(const std::string& pathToTextureImage) { ... }
}
I can easily fix the error by slapping an internal::texture in front of the function call but since I'm using the using namespace internal::texture directive, the compiler should be able to pick it up.
I can also move the CreateTexture function from the namespace internal::texture to doa::texture. But I would like to avoid that.
How can I fix this without moving the function or putting internal::texture in front of the call, and why this thing happens in the first place? This is simply a case of function overloading, why do namespaces cause such a thing to happen? Thank you.
P.S. The functions are defined in a separate file. like this:
//irrelevant implementation details are left out
namespace doa::texture {
Texture* const CreateTexture(const std::string& name, const std::string& pathToTextureImage);
}
namespace internal::texture {
Texture* const CreateTexture(const std::string& pathToTextureImage);
}
I'm going to try to put a few pieces of the C++17 standard (draft) together, and hope I'm not misinterpretting it :)
From the unqualified name lookup:
1 In all the cases listed in 6.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.
2 The declarations from the namespace nominated by a using-directive become visible in a namespace enclosing the using-directive; see 10.3.4. For the purpose of the unqualified name lookup rules described in 6.4.1, the declarations from the namespace nominated by the using-directive are considered members of that enclosing namespace.
From using directive
2 A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (6.4.1), the names appear as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [Note: In this context, “contains” means “contains directly or indirectly”. —end note]
From Name Hiding
1 A name can be hidden by an explicit declaration of that same name in a nested declarative region or derived class (13.2).
Specifically, with this last part, I believe it means that the CreateTexture function in doa::texture hides the CreateTexture in internal::texture even though it is within a different namespace. Basically, the compiler sees CreateTexture in the doa::texture namespace, then stops looking, and hence ignored the one from internal::texture
What is the meaning of the highlighted sentence below? Does it have anything to do with function templates?
[over.load]/1:
Not all function declarations can be overloaded. Those that cannot be
overloaded are specified here. A program is ill-formed if it contains
two such non-overloadable declarations in the same scope. [ Note: This
restriction applies to explicit declarations in a scope, and between
such declarations and declarations made through a using-declaration
([namespace.udecl]). It does not apply to sets of functions fabricated
as a result of name lookup (e.g., because of using-directives) or
overload resolution (e.g., for operator functions). — end note ]
You can do something like this:
namespace N {
void f(int);
}
namespace M {
int f(int);
}
using namespace N; // ok
using namespace M; // ok
// even if both have conflicting f's
You aren't directly overloading anything here. The using directives allow name lookup to find both functions and it's at that point that the call is ambiguous.
Here the sets of functions contain two non-overloadable are in there, but since they are found by name lookup as per the quote, they're okay.
Consider the following program:
namespace foo {
namespace sub {
int f();
} // namespace sub
} // namespace foo
namespace bar {
namespace sub {
int g() {
using namespace foo;
return sub::f() + 1;
}
} // namespace sub
} // namespace bar
I expect this to compile, but - it doesn't:
$ g++-6 -c a.cpp
a.cpp: In function ‘int bar::sub::g()’:
a.cpp:12:9: error: ‘f’ is not a member of ‘bar::sub’
return sub::f() + 1;
^~~
a.cpp:12:9: note: suggested alternative:
a.cpp:3:5: note: ‘foo::sub::f’
int f();
^
no luck with clang either:
$ clang++-6.0 -c a.cpp
a.cpp:12:9: error: no member named 'f' in namespace 'bar::sub'; did you mean 'foo::sub::f'?
return sub::f() + 1;
^~~~~~
foo::sub::f
a.cpp:3:5: note: 'foo::sub::f' declared here
int f();
^
1 error generated.
and it knows which function I want, too!
Now, I understand that things could be ambiguous if I had both a foo::sub::f and a bar::sub::f here. But - why is bar::sub "hiding" foo::sub even when I explicitly ask to use foo::sub functions?
To be clear about what an answer might:
An explanation why this is the (most) reasonable behavior and my expectation is unreasonable.
The rationale for it being this way in the C++ standard.
A quotation from standard saying this needs to be the case; maybe the context will help me understand why this was decided.
Motivation: I've written my code so that the last namespace before the function is part of the method name, in the sense that you wouldn't understand what the function does without prepending the namespace. So instead of saying sub_f() like I would in C, I want to be able to say sub::f(). It's proving difficult to do so without prepending a much longer path of namespaces.
[namespace.udir] says (emphasis mine):
-2- A using-directive specifies that the names in the nominated namespace can be used in the scope in which the using-directive appears after the using-directive. During unqualified name lookup (6.4.1), the names appear
as if they were declared in the nearest enclosing namespace which contains both the using-directive and the nominated namespace. [Note: In this context, “contains” means “contains directly or indirectly”. — end note]
In your example "the names in the nominated namespace" is just foo::sub because that's the only name declared in namespace foo, and the "nearest enclosing namespace which contains both the using-directive and the nominated namespace" is the global namespace. So foo::sub appears (for the purposes of name lookup) as though it were in the global namespace, like this:
namespace sub {
int f();
} // namespace sub
namespace bar {
namespace sub {
int g() {
return sub::f() + 1;
}
} // namespace sub
} // namespace bar
Now it should be more obvious that sub::f won't find anything. Name lookup for sub::f starts by looking for sub. It doesn't find it in the enclosing namespace (which is bar::sub) so it looks in the next innermost enclosing scope (which is bar) and there it finds sub. At that point name lookup for sub stops, it doesn't look in the global namespace where it would find foo::sub made visible by the using-directive.
The next step of name lookup tries to find f in the scope it found for sub, but there's no f in the namespace it found, so name lookup fails.
Using-directives do not work like adding a using-declaration for every member of the namespace, they are "weaker" than using-declarations. The reason for that is so that names really declared in a namespace take priority over names simply made visible by a using-directive. rodrigo's answer to a related question explains that in more detail.
I think the relevant part of the standard that prevents what you are trying to do is this:
6.3.10 Name hiding [basic.scope.hiding]
...
4 During the lookup of a name qualified by a namespace name, declarations that would otherwise be made visible by a using-directive can be hidden by declarations with the same name in the namespace containing the using-directive;
You have sub in both foo and bar namespaces. And the sub in bar is hiding the sub in foo in spite of the using directive. And that is the reason why the f() in foo::sub is also not visible.
An answer to your first point:
What happens when you add to your program a:
namespace sub
{
int f();
}
What should now the compiler choose:
::sub::f() or (using ::foo::)sub::f() ?
According to unqualified lookup in cppreference.com:
For a name used in the definition of a function, either in its body or as part of default argument, where the function is a member of user-declared or global namespace, the block in which the name is used is searched before the use of the name, then the enclosing block is searched before the start of that block, etc, until reaching the block that is the function body. Then the namespace in which the function is declared is searched until the definition (not necessarily the declaration) of the function that uses the name, then the enclosing namespaces, etc.
So I thought function names defined in global namespace scope shall be found simply through unquailifed lookup. However, the following piece of code fails to compile:
#include <iterator>
#include <iostream>
namespace AA{
class AAA{};
};
using namespace AA;
int begin(AAA ){
return 3;
}
int main(){
using std::begin; // to add std::begin in the name candidate set
auto x = AAA();
return begin(x); // compile error, ::begin cannot be found
}
Both GCC(6.1.1) and Clang(3.8.0) reports the same error.
And, either I remove the using std::begin statement or move class AAA to namespace AA, the above program compiles successfully. So I think once my begin is found through name lookup, it will be chosen through overload resolution. Therefore the question is: why my begin function declared and defined in global scope is simply not found in the code case above?
Note that unqualified name lookup will stop if the name is found (at some scope), then the further scopes won't be searched. For your sample code, the name begin will be found at the function scope of main(), (which refers to std::begin), then name lookup stops, so the name in global scope won't be examined.
..., name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.
From the quotation you posted (emphasis added by me):
etc, until reaching the block that is the function body. (the name lookup will stop here, i.e. in the block of main() function body)
Then the namespace ... (The further namespace won't be searched.)
In Wikipedia article below quote is mentioned:
ADL only occurs if the normal lookup of an unqualified name fails to
find a matching class member function. In this case, other namespaces
not considered during normal lookup may be searched where the set of
namespaces to be searched depends on the types of the function
arguments.
So, I was expecting below program would compile fine, but it doesn't:
namespace N1 {
class A {};
void foo (A *p) {}
}
namespace N2 {
void foo (N1::A &p) {}
}
int main () {
N1::A xa;
foo(&xa); // ok
foo(xa); // error: cannot convert ‘N1::A’ to ‘N1::A*’ for argument ‘1’ to ‘void N1::foo(N1::A*)’
}
I searched several questions in SO, but couldn't find which lists the requirements or situations in simple word which suggests: When the ADL kicks in ?
A little more detailed answer would be really helpful to me and future visitors.
It shouldn't compiles. A is in namespace N1. How compiler should knows, that you want to call N2::foo?
n3376 3.4.2/2
For each argument type T in the function call, there is a set of zero or more associated namespaces and a
set of zero or more associated classes to be considered. The sets of namespaces and classes is determined
entirely by the types of the function arguments (and the namespace of any template template argument).
Typedef names and using-declarations used to specify the types do not contribute to this set. The sets of
namespaces and classes are determined in the following way:
If T is a class type (including unions), its associated classes are: the class itself; the class of which it is a
member, if any; and its direct and indirect base classes. Its associated namespaces are the namespaces
of which its associated classes are members. Furthermore, if T is a class template specialization,
its associated namespaces and classes also include: the namespaces and classes associated with the
types of the template arguments provided for template type parameters (excluding template template
parameters); the namespaces of which any template template arguments are members; and the classes
of which any member templates used as template template arguments are members. [ Note: Non-type
template arguments do not contribute to the set of associated namespaces. — end note ]
ADL kicks in pretty much always, as soon as your function takes user a user defined type. It's kicking in for foo here: xa is defined in N1, so foo is searched in N1 as well as in the global namespace. (Without ADL, foo would only be searched in the global namespace.)
And I don't see why you would expect the second call to foo to compile. The type of xa is defined in N1, so ADL adds N1 to the search path, but there's nothing in the expression to imply N2.
It says "other namespaces" are searched. It doesn't say "all namespaces" are searched.
The rules for what extra namespaces are included in ADL are a little complicated, but the most important one is the namespace in which A is defined. That's why your first foo is found. Your second foo can't be found because namespace N2 is nothing to do with anything, and it is not searched by ADL.
If unqualified Name Look-up fails, then look-up proceeds using the argument of the function's call.
Example
func(A x);
Then compiler will look at namespace up starting at namespace including class A. One example is this
// argument_dependent_name_koenig_lookup_on_functions.cpp
namespace A
{
struct X
{
};
void f(const X&)
{
}
}
int main()
{
// The compiler finds A::f() in namespace A, which is where
// the type of argument x is defined. The type of x is A::X.
A::X x;
f(x);
}
More here
http://msdn.microsoft.com/en-us/library/60bx1ys7.aspx
The compiler stops lookup once he has found a function with a matching name. It does not continue searching if the argument types or accessibility (public/protected/private) actually prevent using the function in the current context. Hence in your example, the compiler has no change to "see" N2::foo, since N1::foo is found first.
Note that in your example, N2::foo wouldn't be found even if N1::foo did not exist, as you have no reference to N2 anywhere inside main, so N2 will not be searched at all.