My colleague defined a bunch of functions (which should be in my opinion free functions) inside a stateless class as static member functions.
Since this class is defined and uses types from a nested namespace, I'd like to use ADL to write less non-usefull code. But doesn't their choice just broke the purpose of ADL?
namespace nested_long_namespace_name
{
struct type {};
struct interface { static void f(type) {} };
}
int main()
{
nested_long_namespace_name::type value{};
f(value); // ERROR (ADL does not kick in)
interface::f(value); // ERROR (ADL does not kick in)
nested_long_namespace_name::interface::f(value); // OK
}
Now, my question is: is there a workaround other that defining f as a free function in the namespace nested_long_namespace_name?
Argument-dependent lookup only finds declarations declared in namespaces, and only happens during unqualified lookup. So ADL would never apply to interface::f(value), but it does apply to f(value). But the name f is only going to be looked for under namespace nested_long_namespace_name - we're not going to continue looking in classes declared in those associated namespaces for static functions or data members that named f.
This follows the typical name lookup model - you can have a using-directive to bring a namespace into scope, but there's no equivalent to bring static class members into scope.
So yes, interface::f cannot be found by ADL.
Related
In this example why do I need to qualify the function call B::F() with its namespace? As the typedef of QF should match the type Q as I thought it was an alias for it, not really a new type?
Is there an elegant way around this that doesn't require a using statement in every function body?
namespace A
{
template<class T> struct V {};
template<class T> struct Q {};
typedef Q<float> QF;
template<class T>
inline void F(V<T> v) {}
namespace B
{
template<class T>
inline void F(Q<T> q) {}
}
namespace C
{
void Test();
}
}
using namespace A;
using namespace A::B;
void A::C::Test()
{
QF q;
// using namespace A::B; // Uncomment will work
F(q); // Error, tries A::F() and can't find B::F()
B::F(q); // Ok it uses B::F() as intended
}
int main()
{
return 0;
}
I'll try to show in what ways clang interprets the draft differently than gcc and msvc. When you call F(q) inside the definition of void A::C::Test(), the compiler tries to look up the name F in the scopes in which that call is made, and will stop looking for larger scopes as soon as that name (name, not particular overload) is found. The body of void A::C::Test() is inside the namespace C which is inside A which is inside the global namespace. So when you write the using directive in the global scope, the relevant passage in the standard [basic.lookup.unqual]:
In all the cases listed in [basic.lookup.unqual], 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.
The declarations from the namespace nominated by a using-directive become visible in a namespace enclosing the using-directive; see
[namespace.udir]. For the purpose of the unqualified name lookup rules
described in [basic.lookup.unqual], the declarations from the
namespace nominated by the using-directive are considered members of
that enclosing namespace.
by point 2 implies that the name F (coming from A::B::F) is visible as if it was declared in the global scope, but by point 1 name lookup will find a name F sooner, in namespace A and will not look further. So it only finds void F(V<T> v) and this declaration is not fit for the call.
The more interesting story is with the using directive put inside the body of the function. The difference in approach is whether the definition of void A::C::Test() (which is also a declaration) appears in the global namespace or in namespace A::C. If you take the view that this is the global namespace (as clang apparently does), then the namespace enclosing the using-directive written inside the function is the global namespace and we are back to the explanation above. But if you believe that it appears in namespace A::C, then you bring in (among others) the declaration of void F(Q<T>) into A::C and regular lookup finds it.
A bonus observation is why you would still be able to call F(V<double>{}) since now the declaration void F(Q<T>) is in a narrower scope - and the answer is argument-dependent lookup, the namespace where V<T> is declared is going to be looked at too.
That's a story to scare the learner, but if you want practical guidance, do not use the shortcut with namespaces, use
namespace A::C
{
void Test()
{
...
}
}
so that the namespace in which it is declared is not subject to debate and put using namespace A::B; either in namespace scope or in function scope.
(And I'll try to figure out what was the real intended scope of the void A::C::Test() declaration-definition with wiser people).
I have a following snippet code of c++. Declared a class inside main() function.
What is the reason to we can not define friend function in local class?
#include<iostream>
int main()
{
class Foo
{
void foo() {} // Ok
friend void Bar(){}; // Error
};
}
There's a practical reason. First and foremost, an inline friend definition cannot be found by either qualified or unqualified lookup. It can only by found by ADL. So if we take the class from your example, put it in global scope and try to call Bar:
class Foo
{
friend void Bar(){};
void foo() {
Bar();
}
};
We'll be notified that Bar was not declared in that scope. So if it was in a local class. You can't call it from the members. You can't call it inside the function. The only way you may call it involves either some hoops or ADL. So the language just doesn't allow for it. It's not deemed a useful feature.
There is no convincing technical reason for this. ADL can't find it, you say? Well, that's basically part of the question: why can't ADL find it? Just extend ADL to make it find it.
One design-level reason for this limitation is probably rooted in the language treatment of unqualified names in friend declarations.
Unqualified names used in friend declarations in local classes refer to names from nearest enclosing non-class scope. This treatment of unqualified names is critically important, since this is the only way local classes can refer to each other (since for obvious reasons, local classes do not have qualified names)
int main()
{
class B;
class A {
int x;
friend B; // refers to local `B`
};
class B {
void foo(A &a) { a.x = 42; }
};
}
This rule is also applied to friend function declarations with unqualified names. C++ does not have local functions, but such friend declarations can still refer to a local non-defining declaration of a function (which is perfectly legal)
void foo() {}
int main()
{
void foo(); // refers to `::foo`
class A {
friend void foo(); // refers to local `foo`, which is `::foo`
};
}
Now, what would you propose should happen when one defines a friend function in a local class (using an unqualified name, of course)? What function is introduced by such a declaration? Into what scope, specifically? By definition, it is not a member of the class, since friend declarations do not introduce class members. It cannot be a member of the nearest enclosing local scope, since that would make it a local function and C++ does not support local functions.
We cannot just uniformly change the behavior of all unqualified names in friend declarations and say that they should now refer to names in the nearest enclosing namespace scope, since that would leave as with no way to refer to local classes (as shown above).
The only way out of this situation is to make only in-class friend function definitions refer to (and define) functions in the nearest enclosing namespace scope. Such functions would only be callable through [modified] ADL (and let's say we are OK with that). But that would mean that we'd have to give different treatment to unqualified names in friend function definitions (as opposed to non-defining friend declarations). This would be rather inelegant and confusing. So, the language authors decided against it.
Note that importance of this might have increased notably after C++14, which gave us deduced auto return types in functions. After that local classes became not even nearly as "local" as they used to be
auto foo()
{
struct S // Local class
{
void bar() {}
};
return S();
}
int main()
{
auto a = foo();
a.bar(); // An object of local class used outside of its original scope
typedef decltype(a) S; // Local type is "stolen" from its original scope
S b; // and used to freely declare objects in a completely
b.bar(); // different scope
}
Because member functions of a local class have to be defined entirely inside the class body and friend function not a member function. We declared friend functions inside class and defined outside of class.
According to cppreference:
Local classes
A local class cannot have static members
Member functions of a local class have no linkage
Member functions of a local class have to be defined entirely inside the class body
Local classes other than closure types (since C++14) cannot have member templates
Local classes cannot have friend templates
Local classes cannot define friend functions inside the class definition
A local class inside a function (including member function) can access the same names that the enclosing function can access.
I am unsure if the two data member declarations in class B are equivalent.
//file0.h
namespace C
{
typedef int Id;
}
//file1.h
namespace A
{
typedef int Id;
}
//file2.h
namespace A
{
class B
{
public:
// ...
//Want to add data member theId as:
//Id theId;
//or
//A::Id theId;
}
}
That is, in the absence of A::, is there a default namespace the C++ standard uses in cases like this one? e.g., it may default to namespace A because the class is being declared in it.
If one uses Id theId, which namespace would it use, A or C?
Edit 1: Commented out code to avoid confusion.
Edit 2: Added another "theId" with a different namespace to illustrate better the question.
Answer is Id results in A::Id theId.
Why?
Id (without the A::) is an unqualified name. C++ then resorts to this rule to find the right Id:
Member function definition For a name used inside a member function
body, a default argument of a member function, exception specification
of a member function, default member initializer, or inside a nested
class definition (including names of the bases from which the nested
class is derived), the scopes searched are the same as in class
definition,[...]
[Class definition] the following scopes are searched:
d) if this class
is a member of a namespace, or is nested in a class that is a member
of a namespace, or is a local class in a function that is a member of
a namespace, the scope of the namespace is searched until the
definition of the class, enclosing class, or function. if the lookup
of for a name introduced by a friend declaration: in this case only
the innermost enclosing namespace is considered, otherwise lookup
continues to enclosing namespaces until the global scope as usual.
Reference: http://en.cppreference.com/w/cpp/language/unqualified_lookup
For the following snippet:
class A{
friend void f(){};
public:
A(){f();} //error
};
class B{
friend void f(void* ptr){};
public:
B(){f(this);} //no error
};
According to the rule that although friend functions can be defined inside a class, yet they are not visible until they are declared somewhere outside the class scope, the error in the definition of class A is explained.
But I am confused why the snippet for class B doesn't produce the same error as class A's.
Please can anyone tell me about this?
"Not visible" is a bit of an over-simplification. With only an in-class definition, a friend function can't be found by qualified or unqualified lookup, which is why the first snippet fails.
However, it can be found by argument-dependent lookup (ADL), so you can call it with an argument involving a type that's scoped in the same namespace as the function.
In this case, the argument type is B*, scoped in the global namespace. The friend function is scoped in the namespace containing the class that declares it - also the global namespace. So ADL will look in the global namespace for functions called f, find the friend function, and use that.
Like :
using ::size_t; using ::fpos_t; using ::FILE;
In fact it's a question inspired by the comment under this question:
When is .h not needed to include a header file?
This is called using declaration. There are actually two ways you can use the using keyword. There is a third special form of using declarations used inside class definitions, but i'll focus on the general using declaration here. (see below).
using declaration
using directive
These have two very different effects. A using declaration declares a name to be an alias to another declaration or a set of declarations (if you were to name a set of overloaded functions). The name is declared in the current scope. That is, you can use it inside blocks too
int main() {
using std::swap;
// ...
}
This is quite useful if you use a name very often locally and you don't want to prefix it in all uses, and it's also useful in implementing the swap using argment dependent lookup idiom.
A using directive names a namespace and does not declare any names. Instead it will modify name lookup to find names that aren't really declared where it thinks they are. For unqualified name lookup, it find names declared in the enclosing namespace that encloses both the using directive and the target namespace. All names that are declared in the target namespaces will be found:
int cout;
int main() {
using namespace std;
// cout << 1; ambiguous!
}
Here, cout will be thought as being declared twice in the global namespace, and causes an ambiguity (:: encloses both main and std). In qualified namelookup, it will build the transitive closure of a namespace with all the namespaces named in using directives.
using namespace foo;
int main() {
::c++;
}
c is not only looked up in the global namespace, but also in the namespace foo and in the namespaces that foo has using directives for and so on. If however the global namespace would contain a direct declaration (including a using declaration), that declaration will hide the declarations found indirectly by using directives:
using namespace foo;
int c;
int main() {
::c++; // not ambiguous!
}
Using declarations can appear in many places, including inside class definitions. Its meaning is similar to its meaning otherwhere with an important restriction: It declares a name to be an alias to one or more declarations, but the declarations must be members of a base class. This is very useful for making names visible in a derived class that would otherwise be hidden by the same name declared there
struct base {
void f();
};
struct derived : base {
using base::f; // name "f" declared in derived
void f(int); // overloads the using declaration
};
Now you can call d.f(). If there were no using declaration, then name lookup would only find one declaration of f in derived and stop lookup, not delving into the base class scope:
derived d;
d.f(); // invalid without the using declaration
d.f(0); // valid with or without the using declaration
// explicitly starting lookup in base: valid with or without the using declaration
d.base::f();
It also allows to change the accessibility of base-class members, although you should use that sparingly :)
In practice, i found it useful for making virtual member function re-visible:
struct base {
virtual void f();
virtual void f(int);
};
struct derived : base {
// using base::f; would solve it
virtual void f() { ... }
};
Oops - now d.f(0); is invalid because name lookup only finds the zero parameter f! The using directive would solve it. Notice that if you alias a function declaration that has the same parameter types and constness as an explicit declaration (like f() in this case), then the explicit declaration will still hide the one that the using declaration is an alias for - so both f() functions won't conflict in this case.
An alternative to solve this is using the non-virtual interface idiom
struct base {
void f() { do_f(); }
void f(int) { do_f(0); }
private:
virtual void do_f();
virtual void do_f(int);
};
struct derived : base {
private:
virtual void do_f() { ... }
};
struct derived1 : derived {
private:
virtual void do_f(int) { ... }
};
Now, both d.f(0) and d.f() are valid no matter on what object you call it.
Unfortunately the example you're looking at is obscure.
using ::_Filet;
As others have noted, the using declaration makes a name from the specified namespace available in the current namespace. In that file there appear to be no namespaces opened, so you'd assume the current namespace is the global namespace, and also the :: with nothing before it addresses the global namespace. So here we seem to be moving a name from the global namespace into the global namespace. What's up with that?
The answer is in the use of a macro:
_STD_BEGIN
This is defined as namespace std {. So what the using declarations are doing is making those names appear in the std namespace, where otherwise they would only be in the global namespace.
using <some symbol> pull a symbol from its namespace into the current namespace. Assume the following code:
namespace foo {
// Assume you want to use std::string, you can either do
std::string bar;
// or
using std::string;
string bar;
}
As you can see, you can either qualify the symbol using its namespace (first line of code) or the second way. For symbols you use quite often, pulling them into the namespace tends to make the code a little more readable but if you have a conflict (say, foo contains a string class of its own which is bad practise but might happen), qualifying it with the appropriate namespace will allow you to resolve the conflict.
The namespace :: is a special case as it refers to the global namespace; in this particular case, the functions you're referring to are C functions and C doesn't know about C++ namespaces, so they end up in the global namespace.
Namespaces in C++ are a very powerful mechanism to avoid symbol naming clashes and I'd strongly encourage any C++ programmer to use them.
The 'using' keyword allows you to bring names from a namespace into the current namespace.
If you would like to use a name inside a namespace without bringing them into your current namespace, you would have to use the <namespace name>::<name> format, as in the following:
std::cout << "Hello World";
If cout is brought into the current namespace, then you can use it like below:
cout << "Hello World";
The using keyword can be used the following ways:
As a using directive (using namespace <namespace name>;):
using namespace std;
This brings all names inside the std namespace into the current namespace.
As a using declaration (using <namespace>::<member name>;):
using std::cout;
This brings only the std::cout name into the current namespace.
using makes a name from the specified namespace available in the current namespace.