a theoretical question - can an inner definition function overload an outer definition?
For example:
int foo(){
class x{
public:
int foo() { return 1; }
int bar() { return foo(); }
}
return 0;
}
The inner foo hides the outer one in class x. Can someone give an example of an inner function overloading an outer function, and not hiding it?
Thank you!
I think you mean whether a member function can overload a namespace scope function.
The word overload here essentially means that two or more functions with different signatures (number of arguments and/or their types) are accessible visible to name lookup, and have the same name.
I don't think it's possible to overload so that the same unqualified name can stand for either member function or namespace scope function depending on arguments. E.g.,
#include <cmath> // std::sin
struct S
{
void sin() const { cout << "By Odin!" << endl; }
void foo()
{
using std::sin;
sin( 3.14 ); // OK.
//sin() !Will not find the member func.
}
};
Conversely, without the using declaration the member function can be called unqualified, but not the namespace scope function.
Function overloading means that you have two functions with the same name, but different parameters. You could have a function foo(int a) and then define a function foo(double a) without hiding the other one.
Related
I would like some light to be shed on a puzzling situation involving ADL, namespaces and operator overloading.
Let Foo be a library which defines a class ( Deriv) in its own namespace, along with a templated operator * which returns another class.
namespace Foo {
class Deriv {};
class Another {};
template <typename T>
Another operator* ( T x, const Deriv& d ) { return Another();}
}
Now I use Foo's class in my own library Bar, which defines another operator *, this time only for float.
namespace Bar {
typedef Foo::Deriv MyDeriv;
MyDeriv operator* (float x, const MyDeriv& d) { return MyDeriv();}
}
I observe a difference in compiler behaviour depending whether one is inside namespace Bar or not.
This function (Bar::f1) compiles, using the second version of the operator * :
namespace Bar {
void f1() {
Bar::MyDeriv a;
Bar::MyDeriv b = 3.f * a;
}
}
while the same function outside namespace Bar (f2()) fails to compile, because the compiler attempts only to use Foo::operator* and cannot guess that it must use Bar::operator*.
void f2() {
Bar::MyDeriv a;
Bar::MyDeriv b = 3.f * a; // Error : cannot convert Foo:Another to Bar::Myderiv
}
You can see the code live here :http://ideone.com/pkPeOY
Now, if Foo::operator* was not templated and defined as Foo::operator*(float, const Deriv& d); then both functions fail to compile with the same error (ambiguous operator overload), as can be seen here : http://ideone.com/wi1EWS
So, facing this situation, this is what is puzzling me
In the templated case, when compiling f2, the compiler considers using Foo::operator* but not Bar::operator*, while in the non-templated case, it considers using both (and refuses to go further because of the ambiguity). What makes the compiler behave differently ?
A user of my library Bar will be outside the Bar:: namespace, yet I want Bar::operator* to be used, and not Foo::operator*. I considered explicitely calling Bar::operator*(3.f,a), which is ugly, or inserting my own operator in the global namespace, which I reckon is a Bad Thing. Is there an option I am missing, or am I doing something wrong ?
In the templated case, when compiling f2, the compiler considers using Foo::operator* but not Bar::operator*, while in the non-templated case, it considers using both (and refuses to go further because of the ambiguity). What makes the compiler behave differently ?
In both cases the compiler considers using both, but in the case of a templated operator*, the call is not ambiguous since there is a non-templated function which parameter types perfectly matches the arguments (try replace 3.f with 3. and you will see that the templated version is found). Typically:
template <typename T>
void g (T) { }
void g (float) { }
g(0.f); // Ok, the overload for float is preferred over the templated version
A user of my library Bar will be outside the Bar:: namespace, yet I want Bar::operator* to be used, and not Foo::operator*. I considered explicitely calling Bar::operator*(3.f,a), which is ugly, or inserting my own operator in the global namespace, which I reckon is a Bad Thing. Is there an option I am missing, or am I doing something wrong ?
Unfortunately, ADL will not find your overload since the only parameters of operator* are float and MyDeriv which are defined inside the namespace Foo. One possible way would be to inherit from Foo::Deriv:
namespace Bar {
struct MyDeriv: public Foo::Deriv {};
MyDeriv operator* (float x, const MyDeriv& d) { return MyDeriv();}
}
Another one is to declare your overload for operator* inside the Foo namespace:
namespace Bar {
typedef Foo::Deriv MyDeriv;
}
namespace Foo {
Bar::MyDeriv operator* (float x, const Bar::MyDeriv& d) { return Bar::MyDeriv(); }
}
§14.8.2/4 allows the instantiation of two different functions, g<int> and g<const int> from the template definition. Why doesn't the Standard allow the definition of the two functions f in the code below? I know that both functions would have the same type void(int). But that also happens with the instantiated functions g. The note in §14.8.2/4 says: f<int>(1) and f<const int>(1) call distinct functions even though both of the functions called have the same function type..
#include <iostream>
template<typename T>
void g(T t) { std::cout << t << '\n'; }
void f(int i) { std::cout << i << '\n'; }
//void f(int const i) { std::cout << i << '\n'; } // doesn't compile
int main()
{
g<int>(1);
g<int const>(2);
}
Top-level consts on the parameter types are not part of the function signature. So the two versions of f() you've defined are the same function as far as overload resolution is concerned making the second one a redefinition.
From §13.1/3 [over.load]
— Parameter declarations that differ only in the presence or absence of const and/or volatile are equivalent. That is, the const and volatile type-specifiers for each parameter type are ignored when determining which function is being declared, defined, or called. [ Example:
typedef const int cInt;
int f (int);
int f (const int); // redeclaration of f(int)
int f (int) { /* ... */ } // definition of f(int)
int f (cInt) { /* ... */ } // error: redefinition of f(int)
—end example ]
Only the const and volatile type-specifiers at the outermost level of the parameter type specification are ignored in this fashion; const and volatile type-specifiers buried within a parameter type specification are significant and can be used to distinguish overloaded function declarations.
The fact that top-level const is not part of the function signature allows for a minor advantage.
Suppose you have a function"
void f(int);
in its implementation, if you know you are not going to change the input parameter, you can declare:
void f(int const x) {
std::cout << x << "\n";
}
and this is none of the business of the caller. Later, it turns out it would be useful to munge the input value (say, you want to treat negative integers as 0):
void f(int x) {
if (x<0) x = 0;
std::cout << x << "\n";
}
and without changing the signature or the rest of the body of the function, we are good to go.
Basically, the top level constness of arguments doesn't impact the usual binary calling conventions of C++, and logically the constness is no business of the caller. By eliminating that from the signature, we get some benefit.
For template functions, however, the types impact both the signature and the body of the function, and that body is part of the template's interface. (decltype lets the types of function parameters impact the body, but the body is not part of the interface like a template)
There are 3 examples:
I.
int foo(int i){ return 0; }
namespace A
{
int foo();
int a = foo(5);//Error: too many argument to function int a::foo()
}
II.
namespace A
{
int foo(int i){ return 0; }
int foo(){ return 1; }
int a = foo(5);//OK, Call A::foo(int)
}
III
namespace A
{
int foo(){ return 1; }
int foo(int i){ return 0; }
int a = foo(5);//OK, Call A::foo(int)
}
What exactly rules used to determine the set of candidate functon? I thought that (3.4.1/1)
name lookup ends as soon as a declaration is found for the name.
It is unclear what declaration (int foo(int) or int foo()) will be found first in the cases II and III?
From §13-1 Overloading,
When two or more different declarations are specified for a single name in the same scope, that name is said
to be overloaded. By extension, two declarations in the same scope that declare the same name but with
different types are called overloaded declarations. Only function and function template declarations can be
overloaded; variable and type declarations cannot be overloaded.
Since you have overloaded function declarations in the same namespace, unqualified name lookup finds matches the set of functions and stops. (I admit the standardese seem a bit incorrect here since it says "as soon as a declaration is found for the name".)
So for II and III, unqualified name lookup finds the same set of overloaded functions.
Extending III a bit further,
int foo(int i) { return 42; }
namespace A {
int foo() { return 1; }
int foo(int i) { return 0; }
int a = foo(5); // OK, Call A::foo(int)
}
Now, it may seem as ::foo(int) and A::foo(int) might be ambiguous but it's not because unqualified name lookup stops after finding A::foo() and A::foo(int). Then it's up to overload resolution to pick the best viable function.
Function overloading only works if the functions are in the same namespace. That is, the name is looked up first by namespace, then by the function signature. In case I, there is a function named foo inside of the A namespace, so it tries to call that, but there is no definition of foo in that namespace which accepts an integer parameter.
In any case, you can call the global foo function as follows:
int a = ::foo(5);
The double colon, with no namespace prefix accesses the global namespace.
I already know that a function object can be defined in another function's body. While I try to define a simple function in main function, error occurs.
int main(){
void f(){}
return 0;
}
Could a function be defined in another function?
Could a class and some of its member functions defined separately in another function or another class body? (bold words edit)
Is there a rule to follow?
edit:Thank you very much! But I misswrote class body as function, i.e the bold words, and now it is corrected. Could you tell more?
edit2:By the second question I should have writen:could a member function of a class defined in a function named F while the class declaration is also in the function F,and whatif F is a class defination? Just like these two:
//F is a function
int F(){
class A{
int f();
};
int A::f(){}
}
// F is a class
class F(){
class A{
int f();
};
int A::f(){}
}
Could a function be defined in another function?
Not directly. There's no particular reason why not; the language simply doesn't allow it. You can declare a function inside another; but you can only define it in the surrounding namespace.
You can define named lambda variables, and local classes containing member functions.
int main() {
auto l = []{std::cout << "lambda\n";};
struct s {static void f() {std::cout << "member\n";}};
l();
s::f();
}
Could a class and some of its member functions defined seperaterly in another function or another function?
Class members can only be defined inside the class or (for non-local classes) in a namespace. Unless the class is local, you can't define any member inside another function; if it is local, members can only be defined inside the class.
Any function shall be defined in a namespace region outside any other function but may be declared in any function block scope.
For example
#include <iostream>
void f( int ) { std::cout << "f( int )" << std::endl; }
void f( short ) { std::cout << "f( short )" << std::endl; }
int main()
{
void f( int );
f( 1 );
{
void f( short );
f( 2 );
}
}
As for classes then a class can be defined inside a function. In this case it shall not have static member functions and all non-static member functions shall be defined inside the class. For example
#include <iostream>
int main()
{
struct Multiply
{
constexpr unsigned int operator ()( unsigned int x, unsigned int y ) const
{
return ( y == 0 ? 0 : x + operator ()( x, --y ) );
}
};
std::cout << Multiply()( 10, 10 ) << std::endl;
}
If a class is defined in some name space scope then its member functions can be defined separatly.
For example
#include <iostream>
struct Divide
{
constexpr unsigned int operator ()( unsigned int x, unsigned int y ) const;
};
constexpr unsigned int Divide::operator ()( unsigned int x, unsigned int y ) const
{
return ( x < y ? 0 : 1 + operator ()( x - y, y ) );
}
int main()
{
std::cout << Divide()( 100, 10 ) << std::endl;
}
As for lambda expressions they are not functions. In fact they are anonymous local classes with defined operator function.
Could a function be defined in another function?
No. You can declare a function anywhere, but you cannot define (that is, implement) a function inside another function (the exception being lambda functions).
Could a class and some of its member functions defined separately in another function or another function?
I'm not sure what you are asking here because the sentence is not complete. If you are asking if you can define a class inside a function: yes, you can, but its usefulness would be limited since it would only be defined inside the function.
C++11 introduced lambda expression to build a callable object in a function and capture variables. To define a member function in certain place, you'll probably define a lambda member in the class and assign a lambda to it.
I got this example from my book, but I have no idea how to actually call the ticket function. This is the code:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
I get the "candidate function(s) not accessible" error message.
A few points will help you figure out what's going on here:
I) Friend function definitions within classes can only be found by Argument dependent lookup when called from outside the class definition.
II) Function templates that are supplied explicit template arguments do not undergo ADL unless the compiler is given some explicit help in identifying the call as a function call.
III) Argument dependent lookup (ADL) only works for user defined types.
A few examples will better illustrate each of the above points:
//------------------------
struct S
{
friend int f(int) { return 0; } // 1
friend int f(S) { return 0; } // 2
};
S s;
int i = f(3); // error - ADL does not work for ints, (III)
int j = f(s); // ok - ADL works for UDTs and helps find friend function - calls 2 (III)
// so how do we call function 1? If the compiler won't find the name via ADL
// declare the function in the namespace scope (since that is where the friend function
// gets injected)
int f(int); // This function declaration refers to the same function as #1
int k = f(3); // ok - but not because of ADL
// ok now lets add some friend templates and make this interesting
struct S
{
friend int f(int) { return 0; } // 1
friend int f(S) { return 0; } // 2
template<class T> friend int g(int) { return 0; } // 3
template<class T> friend int g(S) { return 0; } // 4
template<class T> friend int g() { return 0; } // 5
};
S s;
int k = g(5); // error - no ADL (III)
int l = g(s); // ok - ADL - calls 4
int m = g<int>(s); // should call 4 - but no ADL (point II above)
// ok so point II above says we have to give the compiler some help here
// We have to tell the compiler that g<int> identifies a function
// The way to do that is to add a visible dummy template function declaration
template<class /*Dummy*/, class /*TriggerADL*/> void g();
int m = g<int>(s); // ok - compiler recognizes fun call, ADL triggered - calls 4
int n = g<int>(3); // still not ok - no ADL for ints
// so how do we call either function 3 or 5 since we cannot rely on ADL?
// Remember friend functions are injected into the outer namespace
// so lets just declare the functions in the outer namespace (as we did above)
// both these declarations of g below refer to their counterparts defined in S
template<class T> int g(int);
template<class T> int g();
int o = g<int>(3); // ok
int p = g<int>(); // ok
// Of course once you have these two declarations at namespace scope
// you can get rid of the Dummy, TriggerADL declaration.
Ok so now lets return to the Vandevoorde example that you quoted, and now this should be easy:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int Manager::counter;
template<class T> int ticket(); // <-- this should work with a conformant compiler
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
Hope that helps :)
Hotfix
There is a hot-fix available, but read the below explanation if you want to understand what's going on.
#include <iostream>
template<typename T> int ticket();
class Manager {
public:
template<typename T>
friend int ticket() {
return ++Manager::counter;
}
static int counter;
};
int Manager::counter; // don't forget the definition
int main() {
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
As the snippet shows, you have to declare the template to make it visible when you call it.
Friend function definitions
This is confusing, since there are some rules in the way in this case. Some basic points, and then some other points.
struct A {
friend void f(A*) { std::cout << "hello"; }
};
What does it do? It defines a friend function. Such a function is a member of the enclosing namespace. It's not a class member, even though it is defined within a class! The fact that it's defined within a class only changes the lexical scope of that function: It can refer to that class' members directly, without preceding the class-name.
Most importantly, though, the function is not visible after being declared. You cannot take its address doing something like this, for example
&f
The only way that the function would work is using argument dependent lookup. A lookup that ends up having that class as its associated class will consider that friend function. That means that the following works:
f((A*)0);
It works because the call includes an argument with type that has the class included. In that case, the class is an associated class, and the friend declaration will be considered.
The following won't work, for example
f(0);
Because it has no idea that it should look within A to find a friend declaration. A friend function definition of a function without an argument won't be found, because there is no argument dependent lookup happening, then.
Friend function definition for templates
In addition to the fact that your call does not include arguments, it has another problem. If you define a friend function template, the matter is more complicated. There is a rule that says that if the compiler sees T<A1, A2, A3>, that this only refers to a template specialization if T actually resolves to a template. Consider
ticket < int > ()
The compiler can't resolve ticket, because it is not visible to normal lookup. Therefor, the rule says that ticket<int> does not refer to a function. It has to be parsed as a relational expression, yielding to the following
(ticket < int) > ()
That will be a syntax error, because int is not a value, and () is neither a value.
Example
Here is an example where it matters.
struct A {
template<int I> friend void f(A*) { }
};
// try to comment this out
template<typename Dummy> void f();
int main() {
f<1>((A*)0);
}
That compiles. It compiles because f resolves to a template (although a completely different one that can't even accept a non-type template argument - but that doesn't matter!). But a Standard conforming compiler will not compile the snippet once you comment out the second declaration, because it's compiled as a relational expression (less-than and smaller-than) and it will not find symbol f.
Read this thread for further information: What am I missing in this template toy example?.
I do get the same error using the MS VS++ compiler. According to the docs on MSDN:
http://msdn.microsoft.com/en-us/library/h2x4fzdz(VS.80).aspx
Friends are not in the class's scope,
and they are not called using the
member-selection operators (. and –>)
unless they are members of another
class. A friend function is declared
by the class that is granting access.
So friend functions are not actually part of the class and should therefore not be defined in class scope. Define the function outside of the class:
#include <iostream>
class Manager {
public:
template<typename T>
friend int ticket();
static int counter;
};
template<typename T>
int ticket() {
return ++Manager::counter;
}
int Manager::counter;
int main()
{
Manager m;
std::cout << "ticket: " << ticket<int>() << std::endl;
}
Why not make it static instead?
#include <iostream>
class Manager {
public:
template<typename T>
static int ticket()
{
return ++Manager::counter;
}
static int counter;
};
int main()
{
Manager m;
std::cout << "ticket: " << Manager::ticket<int>() << std::endl;
}
Though really, it doesn't have to be a template either. I assume you needed information specifically about friend templates?