Impact of namespaces on C++ template deduction priority - c++

while trying to implement a metafunction, which needs to exist only if the "abs" function exists for some type, i ran into the folowing problem:
Here are two examples of code i would expect to yield the same results but in fact, they do not:
First example
#include <iostream>
#include <cmath>
using namespace std;
struct Bar{};
template<typename T>
int abs(T& v)
{
return -1;
}
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
int main()
{
test();
}
Yields:
2
-1
Which is what i expect
Second example
#include <iostream>
#include <cmath>
namespace Foo
{
struct Bar{};
using namespace std;
template<typename T>
int abs(T& v)
{
return -1;
}
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
}
int main()
{
Foo::test();
}
Yields:
-1
-1
Why using a namespace here is making the compiler prioritize the "local" abs methodthe over std::abs?

In the second case the using directive places declared names in the nominated namespace in the global namespace for unqualified name lookup. So within the namespace Foo the unqualified name abs declared in this namespace is found. That is the name abs declared in the namespace Foo hides the name abs declared in the global namespace.
From the C++ 14 Standard (7.3.4 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
(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 ]
The nearest enclosing namespace in the second program is the global namespace.
Below there are two more programs that demonstrate the same principle of the unqualified name lookup when a using directive is used.
#include <iostream>
void s() { std::cout << "The function s() called.\n"; }
struct s
{
s() { std::cout << "The constructor of struct s called.\n"; }
};
void test()
{
s();
}
int main()
{
test();
}
The program output is
The function s() called.
In this demonstration program the declaration of the function s hides the declaration of the structure s.
Second program.
#include <iostream>
namespace N1
{
void s() { std::cout << "The function N1::s() called.\n"; }
}
namespace N2
{
using namespace N1;
struct s
{
s() { std::cout << "The constructor of struct N2::s called.\n"; }
};
void test()
{
s();
}
}
int main()
{
N2::test();
}
The program output is
The constructor of struct N2::s called.
In this case the declaration of the structure with the name s hides the function with the same name s the declaration of which was placed in the global namespace due to the using directive.

For the reason why this takes place you can refer to Vlad's answer. However, if you want to still be able to perform the testing, you can do the testing in separate namespace.
#include <iostream>
#include <cmath>
namespace Foo
{
template<typename T>
int abs(T& v)
{
return -1;
}
}
namespace Test
{
struct Bar{};
using namespace std;
using namespace Foo;
void test()
{
Bar b;
double x = -2;
cout << abs(x) << endl;
cout << abs(b) << endl;
}
}
int main()
{
Test::test();
}
The output is
2
-1

Related

How to use nested namespace to avoid ambiguity?

I have the following operators defined in the corresponding namespaces:
namespace literals
{
constexpr ID operator"" _ID(const unsigned long long dyngateID)
{
// ...
// return a constructed id
}
namespace multiplied
{
constexpr ID operator"" _ID(const unsigned long long dyngateID)
{
// ...
// return an id constructed in a specific way
}
} // namespace multiplied
} // namespace literals
In a .cpp file I would like to use both functions, hence I've declared using namespace literals and when I am declaring using namespace multiplied in a concrete function I am getting ambiguous call to overloaded function compile error. How can I differentiate these functions?
Test.cpp
using namespace literals;
void f()
{
// here I am using literals' _ID which is fine
const Type id{1_ID};
}
void g()
{
// here I want to use multiplied's _ID, but obviously I am failing to do so
using namespace multiplied;
const Type id{1_ID};
}
The name lookup rules for using namespace are such that the declarations introduced by it appear to be located in the inner-most namespace scope enclosing both the current namespace scope and the target namespace scope.
Therefore it is no good to disambiguate based on the scoping of multiple reachable using namespace statements.
Instead you can import the declaration with a using declaration:
void g()
{
using multiplied::operator""_ID;
const Type id{1_ID};
}
This will behave as if the operator was declared in the scope, so that name lookup will stop there and won't look at the declaration imported by the outer using namespace.
Alternatively, you can call the user-defined literal operator directly with a qualified call:
void g()
{
const Type id{multiplied::operator""_ID(1)};
}
As another possibility you can always limit the scope of the using namespace statements, so that only one of using namespace literals; or using namespace literals::multiplied; is reachable from any given scope using the operator, e.g.:
// no using namespace at this scope
void f()
{
using namespace literals;
const Type id{1_ID};
}
void g()
{
using namespace literals::multiplied;
const Type id{1_ID};
}
Consider the following code:
#include <iostream>
namespace one
{
int func(int num1, int num2)
{
return num1 * num2;
}
namespace two
{
int func(int num1, int num2)
{
return num1 * num2;
}
}
}
int f()
{
return one::two(1, 2) + 10;
}
int g()
{
return one::two::func(3, 4) + 10;
}
int main()
{
std::cout << f() << std::endl;
std::cout << g() << std::endl;
}
The above code will compile and run perfectly fine, and will work as expected, with f() using one::func() and g() using one::two::func(). If you have to write `using namespace one;' then you can do something like this:
using namespace one;
int f()
{
return func(1, 2) + 10;
}
int g()
{
return two::func(3, 4) + 10;
}
This will also result in the same output.

A viable function with a default argument

The following example is given in N4296::13.3.3 [over.match.best]
namespace A
{
extern "C" void f(int = 5);
}
namespace B
{
extern "C" void f(int = 5);
}
using A::f;
using B::f;
void use()
{
f(3); // OK, default argument was not used for viability
f(); // Error: found default argument twice
}
I tried to write something similar:
#include <iostream>
namespace A
{
void foo(int a = 5){ std::cout << a << "1" << std::endl; }
}
namespace B
{
void foo(int a = 5){ std::cout << a << std::endl; }
}
using A::foo;
using B::foo;
int main()
{
foo(2); //Error
}
DEMO
But I got a compile-time error. Why does the Standard says that it's OK?
The difference is the extern "C", which affects namespace membership of the function:
From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1997/N1138.pdf
What remains is the definition of “same entity” with respect to ‘extern “C”’ language linkage? This is
addressed by 7.5¶6:
“At most one function with a particular name can have C language linkage. Two
declarations for a function with C language linkage with the same function name
(ignoring the namespace names that qualify it) that appear in different namespace scopes
refer to the same function. Two declarations for an object with C language linkage with
the same name (ignoring the namespace names that qualify it) that appear in different
namespace scopes refer to the same object.”
That's because the two functions are imported from their namespace, this means that the same function has 2 definitions, you can solve it like this:
#include <iostream>
namespace A
{
void foo(int a = 5){ std::cout << a << "1" << std::endl; }
}
namespace B
{
void foo(int a = 5){ std::cout << a << std::endl; }
}
int main()
{
A::foo(2);
B::foo(3);
}

Why do I have to specify the outer namespace for a function in a nested anonymous namespace?

Given a namespace A. Inside is an anonymous namespace with function f and a class X, also with function f: Why do I have to specify the outer namespace A:: as a qualifier when calling anonymous f from A::X::f?
As a minimal example:
#include <iostream>
using namespace std;
namespace A {
namespace {
int f( int i ) { return i; }
}
class X {
public:
static int f() { A::f( 10 ); }
};
}
int main()
{
cout << A::X::f() << endl;
return 0;
}
Because, within the scope of X::f, the unqualified name f refers to X::f, not any other f. A name declared within a scope will hide anything with the same name in an outer scope.

Please help me with C++ Namespace

#include <iostream>
#include <cstdlib>
namespace A {
int a = 10;
void get_value(){ std::cout << "a = " << a << std::endl; }
}
namespace B {
int b;
void get_value(){ std::cout << "b =" << b << std::endl; }
}
void set_B();
int main(){
using namespace A;
get_value();
set_B();
system("PAUSE");
return 0;
}
void set_B(){
using namespace B;
b = 15;
get_value(); // Why call to get_value() is ambiguous, error is not generated here ?
}
Why call to get_value() inside set_B() function is not ambiguous ( A::get_value() or B::get_value()) as both appear as ::get_value() inside set_B().
using namespace A; isn't active inside set_B because it only appears inside main. It is limited to the scope in which it appears: the body of main.
because A::get_value and B::get_value arn't normally visible in the global scope. the using namespace statement makes the declarations in that namespace visible inside set_B.

Using one or more namespaces when conflicting symbols are present?

What are the pro and cons of using two namespaces such as
namespace library1
{
void function1();
}
namespace library1_sublibrary1
{
void function1();
}
instead of
namespace library1
{
void function1();
namespace sublibrary1
{
void function1();
}
}
I would have to fully qualify symbols in the second case, right? Is there any concrete reason (beyond personal taste) why one should be preferred on the other?
Repeating from two comments.
Between the two versions (one: two separate namespaces, two: nested namespaces), there are some differences in name lookup. Most of these can be overcome with either a using-declaration (e.g. using outer::function0;) or a using-directive (e.g. using namespace library1;), but some cannot.
1. unqualified lookup inside the inner namespace
#include <iostream>
namespace outer
{
void function0() { std::cout << "outer::function0" << std::endl; }
namespace inner
{
void test0()
{
function0(); // finds outer::function
}
}
}
namespace another_outer
{
void test0_1()
{
// either
using namespace outer;
// or
using outer::function0;
function0();
}
}
N.B. you can also put the using-directive or using-declaration at namespace scope in another_outer, but some difference remains:
2. stopping unqualified lookup
Unqualified lookup stops in a scope once a name has been found (and then doesn't search the outer scopes). This can be used to hide functions from other scopes. Here's an example of a problem related to this; also see this answer.
void function1() { std::cout << "::function1" << std::endl; }
namespace another_outer
{
void function1() { std::cout << "another_outer::function1" << std::endl; }
}
namespace outer
{
namespace inner
{
void function1() { std::cout << "outer::inner::function1" << std::endl; }
}
void test1()
{
function1(); // finds ::function1
{
using namespace inner;
function1(); // finds (only) outer::inner::function1
}
{
using namespace another_outer;
//function1(); // finds both ::function1 and another_outer::function1
// error: ambiguous call
}
}
}
3. ADL
This isn't about differences between the two variants, but addresses "I would have to fully qualify symbols in the second case, right?".
Argument-dependent lookup happens when you don't qualify the name of a function in a function call. It looks for the name of the function in namespaces (and classes) associated with the arguments.
namespace outer
{
struct ADL {};
void function2(ADL&) { std::cout << "outer::function2" << std::endl; }
namespace inner
{
void function2(ADL const&);
void test2()
{
ADL x;
function2(x); // finds both outer::function2
// and outer::inner::function2
// overload resolution selects outer::function2
}
}
}
int main()
{
outer::ADL x;
function2(x); // finds outer::function2
outer::inner::test2();
// other tests:
outer::inner::test0();
outer::test1();
}
4. Specifically about conflicting symbols
If you have two identical functions (except for the return type) in outer and outer::inner and both are found for some call, that call will be ambiguous. But unqualified lookup might only find one of them:
namespace outer
{
void function3() { std::cout << "outer::function3()" << std::endl; }
namespace inner
{
void function3()
{ std::cout << "outer::inner::function3()" << std::endl; }
void test3()
{
function3(); // only finds outer::inner::function3
}
}
void test3_1()
{
using namespace inner;
//function3(); // finds both outer::function3
// and outer::inner::function3
// error: ambiguous call
using inner::function3;
function3(); // finds (only) outer::inner::function3
}
}
namespace another_outer
{
void function3() { std::cout << "another_outer::function3" << std::endl; }
void test3_1()
{
using namespace outer;
function3(); // still only finds another_outer::function3
using outer::function3;
function3(); // only finds outer::function3
}
}