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
Related
The following code compiles perfectly with the latest MSVC, GCC and CLang available at godbolt online compiler explorer site. I wonder why:
namespace ns
{
struct Test
{
void foo();
};
}
using namespace ns;
// Alert! Member function defined outside its namespace!
void Test::foo()
{
}
int main()
{
ns::Test obj;
obj.foo();
return 0;
}
cppreference claims that if a member function is defined outside its class, then it must be defined at the namespace of that class. See the very top of the cppreference page about member functions.
But still, the compilers accept the code. It's really unlikely that all three independent compilers have the same bug, right? So, is there a good reason behind them accepting such code?
12.2.1 Member functions [class.mfct]
A member function may be defined (11.4) in its class definition, in which case it is an inline member function (10.1.6), or it may be defined outside of its class definition if it has already been declared but not defined in its class definition. A member function definition that appears outside of the class definition shall appear in a namespace scope enclosing the class definition.
This does not mean the definition must appear in the immediately surrounding scope. It can appear in any enclosing namespace, even if that is several layers up.
However, this would be illegal:
namespace a {
struct X {
void Y();
};
}
namespace b { // not an enclosing namespace
void X::Y()
{
std::cout << "Do a thing!\n";
}
}
Quoting C++17 (n4659) 12.2.1 [class.mfct]/1:
A member function definition that appears outside of the class definition
shall appear in a namespace scope enclosing the class definition.
This means it must be defined in the namespace which contains the class, or any parent namespace of that namespace. In your case, it's defined in the global namespace, which does indeed enclose (indirectly) the class definition.
using namespace ns;
5) using-directive: From the point of view of unqualified name lookup of any name after a using-directive and until the end of the scope in which it appears, every name from ns_name is visible as if it were declared in the nearest enclosing namespace which contains both the using-directive and ns_name.
It means that in the current scope ns can be omitted from addressing something inside that namespace.
As such when you write this code:
using namespace std;
vector<string> vectorofstrings;
You don't have to write
std::vector<std::string> vectorofstrings;
The namespace of a class is the name of the class. So if you have:
namespace aNamespace{
class aClass{
int aMember;
void aFunction();
};
}
Then the fully qualified lookup is ::aNamespace::aClass and a function must be defined as being part of void ::aNamespace::aClass::aFunction(){}
Referring to this code:
namespace Y {
char f() { return y; } // error: y was not declared in this scope
char y;
}
struct X {
char f() { return x; } // OK
char x;
};
As per basic.scope.namespace#1:
The declarative region of a namespace-definition is its
namespace-body. Entities declared in a namespace-body are said to be
members of the namespace, and names introduced by these declarations
into the declarative region of the namespace are said to be member
names of the namespace. Its potential scope includes its namespace from the name's point of declaration onwards.
QUESTIONS
Is it correct to say that the error was due to the fact that Y::y is not yet declared in Y::f()?
I can't figure why there isn't a "reodering" for namespace members during declaration while for struct there is. What could be the reason for disallowing such behavior? Does the standard says something similar?
Is it correct to say that the error was due to the fact that Y::y is not yet declared in Y::f()?
Yes.
I can't figure why there isn't a "reodering" for namespace members during declaration while for struct there is. What could be the reason for disallowing such behavior? Does the standard says something similar?
The biggest hindrance for namespaces as opposed to classes, is that they are never "closed". You can always add members to a namespace by re-opening it in another translation unit and declaring more stuff in it. A class declaration however, for all its members, must appear entirely in a single translation unit. And there is no adding to it later.
[class.mem]/1
The member-specification in a class definition declares the full set
of members of the class; no member can be added elsewhere.
The problem for namespaces is intractable. But classes only require a little more, quite localized, work.
It is therefore much easier, both to a language designer and a compiler writer, to demand namespace declarations appear before they are used.
You should also note that you can only use other members of the class in only a specific set of places inside the definition.
[class.mem]/6
A class is considered a completely-defined object type ([basic.types])
(or complete type) at the closing } of the class-specifier. Within the
class member-specification, the class is regarded as complete within
function bodies, default arguments, noexcept-specifiers, and default
member initializers (including such things in nested classes).
Otherwise it is regarded as incomplete within its own class
member-specification.
You are mistaken thinking that for structures there is "reordering".
Consider the following structure definition.
#include <iostream>
struct A
{
char s[N];
enum { N = 10 };
};
int main()
{
return 0;
}
The compiler will issue an error because the name N is not yet declared when it is used in the array declaration. So neither "reordering" exists in the class scope. As for member functions then names used within a member function are at first searched in the class scope.
Moreover a name declared in a namespace can hide the same name declared in the outer namespace. As result the "reordering" breaks scopes of variables.
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.
Here is the corresponding question, what I want to know is, Is it possible to bring global function into the overload resolution with member function?
I tried in 2 ways, but both don't work:
void foo(double val) { cout << "double\n";}
class obj {
public:
using ::foo; // (1) compile error: using-declaration for non-member at class scope
void callFoo() {
using ::foo; // (2)will cause the global version always be called
foo(6.4);
foo(0);
}
private:
void foo(int val) {cout << "class member foo\n"; }
};
I doubt you can make the compiler call one or the other based on the type. You can of course use a local wrapper function, something like this:
void callFoo() {
foo(6.4);
foo(0);
}
private:
void foo(double val) { ::foo(val); }
The wrapper function should nicely inline into nothing, so there is no actual overhead when compiled with optimisation.
Or don't call the member and the global function the same name, which makes life a whole lot easier!
This is plain old unqualified name lookup, specified in §3.4.1 [basic.lookup.unqual]:
1 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.
8 For the members of a class X, a name used in a member function
body, in a default argument, in an exception-specification, in the
brace-or-equal-initializer of a non-static data member (9.2), or in the definition of a class member outside of the definition of X,
following the member’s declarator-id, 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.
Note first that name lookup stops as soon as a declaration is found. So if you have using ::foo; in callFoo(), lookup for foo will end there and never touch the second bullet point; if you don't have it, lookup for foo will find the member foo() at the second bullet point and never search elsewhere. The way unqualified name lookup is specified means that you will either find class members or non-class-members, but never both.
This is also noted in §13.1.1.1 [over.call.func]/p3:
In unqualified function calls, the name is not qualified by an -> or .
operator and has the more general form of a primary-expression. The
name is looked up in the context of the function call following the
normal rules for name lookup in function calls (3.4). The function
declarations found by that lookup constitute the set of candidate
functions. Because of the rules for name lookup, the set of candidate
functions consists (1) entirely of non-member functions or (2)
entirely of member functions of some class T. In case (1), the argument list
is the same as the expression-list in the call. In case (2), the
argument list is the expression-list in the call augmented by the
addition of an implied object argument as in a qualified function
call.
A using-declaration at class scope must name a base class member (§7.3.3 [namespace.udecl]/p3):
In a using-declaration used as a member-declaration, the
nested-name-specifier shall name a base class of the class being defined.
What it appears you are trying to do is use the parameter type to choose the correct overload, and to bring the external foo into your class or member function.
Bringing it into the class is easy. You just declare another overload as a class member that forwards to the external one.
Bringing into the function is tricky but can be done by use of helper functions e.g. fooCaller( double ) and fooCaller( int ) which you can call from callFoo.
If you don't want to expose these to the external user, i.e. hide them away in the cpp file, it can be done but is trickier, due to the fact that foo in your class is private. You would have to have your callFoo function pass in the private function as a member function to "call" for the int overload.
You cannot do that probably because member functions has different signature visible by compiler, which is
void foo(double)
vs
void obj::foo(int)
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.