Consider the following c++ code
class A
{
public:
void doStuff() {};
void callStuff()
{
doStuff(true);
doStuff();
};
private:
void doStuff(bool doIt = false) {};
};
int main()
{
A a;
a.doStuff();
a.callStuff();
return 0;
}
Not surprisingly, GCC gives several errors when compiling this:
overload.cpp: In member function ‘void A::callStuff()’:
overload.cpp:8:10: error: call of overloaded ‘doStuff()’ is ambiguous
doStuff();
^
overload.cpp:8:10: note: candidates are:
overload.cpp:4:12: note: void A::doStuff()
void doStuff() {};
^
overload.cpp:11:12: note: void A::doStuff(bool)
void doStuff(bool doIt = false) {};
^
overload.cpp: In function ‘int main()’:
overload.cpp:17:17: error: call of overloaded ‘doStuff()’ is ambiguous
a.doStuff();
^
overload.cpp:17:17: note: candidates are:
overload.cpp:4:12: note: void A::doStuff()
void doStuff() {};
^
overload.cpp:11:12: note: void A::doStuff(bool)
void doStuff(bool doIt = false) {};
^
I have several questions:
How can I tell the compiler which overload I want to use? Will I be forced to remove one of them?
If I have to remove one of them, how can I find this problem at compile time without trying to call the overload? As long as I am not calling them everything should compile fine so I might only find out later that I am unable to call an overload that I have added once I am trying to call it.
Why does the second error occur? The main function should not be able to access the private overload so it should know which one to use.
How can I tell the compiler which overload I want to use? Will I be
forced to remove one of them?
You can't, just remove or rename one of them.
If I have to remove one of them, how can I find this problem at
compile time without trying to call the overload? As long as I am not
calling them everything should compile fine so I might only find out
later that I am unable to call an overload that I have added once I am
trying to call it.
You can't either. The ambiguity is only detected when you try to call the member function using no arguments. Even if you could perform some compile time checks, there would have to be very specific, and it would be easier to just remove or rename one of the overloads.
Why does the second error occur? The main function should not be able
to access the private overload so it should know which one to use.
Unfortunately, overload resolution occurs before access specifiers are taken into account. Therefore, the compiler doesn't even take into account the fact that one of the overloads is private: the ambiguous call is found before that even happens. I don't really know why this happens this way, but that's what the standard says.
The cause of all your woes are related to your function definitions and their corresponding calls.
So, firstly, the compiler is correct in that your function calls are ambiguous, hence your errors - as it can't distinguish which version is required based on your usage. While member functions can be overloaded, with same name on the same scope, they must have different signatures (a member function's signature is comprised of the member function's name and the type and order of the member function's parameters).
Hence:
void doStuff() {};
void doStuff(bool doIt = false) {};
when called like this:
doStuff();
are equivalent, leading to an ambiguous function call as the compiler can't determine if you want to call:
void doStuff();
or
void doStuff(boo doIt = false);
with a unsupplied parameter value. Function visibility doesn't get to be checked because of the same problem.
The only around this is to change the name of one of the functions or the signature of the functions (while keeping the same name).
Hence, something like this is perfectly legal:
class A
{
public:
void doStuff() {};
void callStuff()
{
doStuff(1, true);
doStuff();
};
private:
void doStuff(int i, bool doIt = false) {};
};
int main()
{
A a;
a.doStuff();
a.callStuff();
return 0;
}
Thus:
Change the name of one of the functions or its signature as well as its corresponding function call.
You can't because it's an ambiguous call. The only solution is to make the suggested changes described above.
What mfontanini said:
Unfortunately, overload resolution occurs before access specifiers are
taken into account. Therefore, the compiler doesn't even take into
account the fact that one of the overloads is private: the ambiguity
is found before that even happens.
See this link for additional reference:
http://www.learncpp.com/cpp-tutorial/77-default-parameters/
You need to remove the default parameters “bool doIt = false”.
class A
{
public:
void doStuff() {};
void callStuff()
{
doStuff(true);
doStuff();
};
private:
//void doStuff(bool doIt = false) {};
void doStuff(bool doIt) {};
};
int main()
{
A a;
a.doStuff();
a.callStuff();
return 0;
}
Related
I am unable to understand the output of the following C++ snippet.
Should not objc.fn() call A's fn() since B's fn() is private and should not be visible in C. However, the answer is: the call to fn() is ambiguous. How?
#include<iostream>
using namespace std;
class A{
public:
void fn() { cout << "1"; }
};
class B{
void fn() { cout << "2"; }
};
class C: public A, public B {};
int main(){
C objc;
objc.fn();
return 0;
}
According to the book C++ Templates: The Complete Guide Appendix B.1,
At a very high level, a call to a named function can be processed in
the following way:
The name is looked up to form an initial overload set.
If necessary, this set is tweaked in various ways (for example,
template deduction occurs).
Any candidate that doesn't match the call at all (even after
considering implicit conversions and default arguments) is
eliminated from the overload set. This results in a set of so-called
viable function candidates.
Overload resolution is performed to find a best candidate. If there
is one, it is selected; otherwise, the call is ambiguous.
The selected candidate is checked. For example, if it is an
inaccessible private member, a diagnostic is issued.
As you can see, the access authority is checked at last, so the call to fn() is ambiguous will be reported firstly at step #4.
Consider this:
class D {
void fn1() {}
public:
void fn2() {}
};
int main() {
D d;
d.fn2(); // Compiles fine
d.fn1(); // Error: fn1 is private
}
Notice that the error for d.fn1() is about fn1 being private, not that fn1 is unknown or invisible in this scope. By the same token, B::fn is indeed visible in C.
We get this behavior because the compiler does name resolution the same for public and private members. Only after the name has been resolved does the accessibility check come into play.
It is the same for your case: Which fn do you mean? Only after you have answered that question can the compiler tell you if you have access to that fn or not.
As I suspected, this code gives an ambiguous reference and does not compile. As you have declared both functions with the same signature, the compiler doesn't know which of the functions to select, giving a complaint at compilation time.
$ make pru
g++ pru.cc -o pru
pru.cc: In function ‘int main()’:
pru.cc:15:8: error: request for member ‘fn’ is ambiguous
pru.cc:9:9: error: candidates are: void B::fn()
pru.cc:6:9: error: void A::fn()
make: *** [pru] Error 1
I think you can select which function to use, placing the A::fn() selector. Even if, as it is the case in this example, one of the functions is private, you have two functions to select from (you could make the call from inside a B method and you'll get the same error ---in that case you have visibility to both methods).
The correct answer has already been given by #songyuanyao.
Checking access specifiers at the last was designed by the C++ Standard Committee.
Had it not been so, the following things would have occurred :
If one modifies their code in future and change the access specifier of their functions, it may break the compilation of the dependent classes.
More horrible yet, you may start calling a totally unrelated function, and would remain oblivious..!!
Let us assume that access specifiers prevent a function from participating in overload resolution, then :
class A{
public:
void fn() { cout << "1"; }
};
class B{
void fn() { cout << "2"; }
};
class C: public A, public B {};
int main(){
C objc;
objc.fn(); // A::fn() is being invoked
return 0;
}
Now we modify the code:
class A{
void fn() { cout << "1"; }
};
class B{
public:
void fn() { cout << "2"; }
};
Nothing else has been touched, and suddenly
objc.fn(); // B::fn() is being invoked
The caller of your function has no idea that his underlying function is not the same anymore.
This is blasphemy !!
To prevent all such mishaps from happening, the Standard Committee took this design decision.
void Parser::add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand)
{
command_no_arg.push_back(comand);
func_no_arg.push_back(f);
}
void Parser::prepare()
{
//add_func_no_arg(Virtual_Machine::dump,"dump"); it work when i put it in static but i cant do that
add_func_no_arg(vm.clear,"clear"); // ERROR HERE the vm.clear does not fit
}
I have those two functions to try help my create a array of pointers func_no_arg;
I can't put the vm's func in static;
Why cant i have a pointer on a function when it is "trap" whit in one objet ? maybe the type is wrong, here is some .hpp :
class Parser {
public:
/***/
void prepare();
void add_func_no_arg(void (Virtual_Machine::*f)(), std::string comand);
private:
Virtual_Machine vm;
std::vector<std::string> command_no_arg;
std::vector<void (Virtual_Machine::*)()> func_no_arg;
/***/
};
class Virtual_Machine {
public:
/***/
void clear();
/***/
}
and the compiler said this :
Parser.cpp: In member function ‘void Parser::prepare()’:
Parser.cpp:65:36: error: invalid use of non-static member function ‘void Virtual_Machine::clear()’
add_func_no_arg(vm.clear,"dump");
^
In file included from ../include/Parser.hpp:13,
from Parser.cpp:8:
../include/VM.hpp:23:14: note: declared here
void clear();
The syntax for getting a pointer-to-member is &Virtual_Machine::clear (not vm.clear), and a variable f of this type can be invoked on an instance of Virtual_Machine with the .* operator (e.g. vm.*f()).
Alternatively you could write &decltype(vm)::clear, which doesn't depend on the class name.
As written by IlCapitano you have to use a specific syntax to deal with pointer-to-members. Here is an example (compiled with g++ tmp.cpp -o tmp):
#include <iostream>
#include <string>
#include <vector>
class Virtual_Machine
{
private:
std::string name;
public:
Virtual_Machine(std::string n) : name(n) {}
void clear() { std::cout << "Clear " << name << std::endl; }
};
class Parser
{
private:
Virtual_Machine vm;
std::vector<std::string> command_no_arg;
std::vector<void (Virtual_Machine::*)()> func_no_arg;
public:
Parser(std::string vm_name) : vm(vm_name) {}
void add_func_no_arg(void (Virtual_Machine::* f)(), std::string command)
{
command_no_arg.push_back(command);
func_no_arg.push_back(f);
}
void prepare()
{
add_func_no_arg(&Virtual_Machine::clear, "clear");
}
void test()
{
(vm.*(func_no_arg[0]))();
}
};
int main()
{
Parser a("vm_a"), b("vm_b");
a.prepare();
b.prepare();
a.test();
b.test();
return 0;
}
The output of the program is:
Clear vm_a
Clear vm_b
A pointer to the member function clear of an instance of class Virtual_Machine is created with &Virtual_Machine::clear. To later call this function you have to use the operators .* or ->* with an instance of the class on the left side of the operator and the pointer to the function on the right side, like (vm.*(func_no_arg[0]))(). If the function would have parameters, you would place them in the most right pair of parentheses.
As mentioned above, the proper syntax to get a pointer to a member functions is &Class::member. The general idea behind this, is that when you declare a class, every function and types in that class belongs in a namespace named after your class. Thus the syntax for getting a pointer to member function is actually equivalent to any pointer to a function inside a namespace. Do keep in mind that access specifier still apply when trying to retrieve a pointer to a function in a class.
However, there is one big difference, in that when you declare a member function, an implicit parameter is added (this in c++), which you actually noted, which is why the type is return_type (Class::*) (parameters)
There are two way to handle this matter. The first one, as noted by others here is to use the instance when you need to call the function, by using the .* or ->* syntax (the dot or arrow are there to access the instance "internals", and the star to de-reference the function pointer).
Another way of doing this (mostly if you don't care about the object, or can't access it when you call it) is to wrap your function in an std::function, by "binding" the implicit this, and any parameter you need to, using std::bind.
By using std::function and std::bind together, you would be able to use the c-style syntax you're used to.
The example section for std::function and std::bind on cppreference show how to achieve this
Condider the following code:
template <class Impl, class Cont>
struct CrtpBase
{
void foo()
{
cout << "Default foo\n";
Cont cont;
cont.push_back(10); // Going to fail if Cont::push_back doesn't exist
}
};
typedef std::unordered_map<int,int> ContType;
struct Child : public CrtpBase<Child, ContType>
{
typedef CrtpBase<Child, ContType> _Parent;
// using _Parent::foo // (1)
void foo() { cout << "Child\n"; }
};
int main()
{
Child obj;
obj.foo(); // (2)
return 0;
}
What I'm stuck at is conditions when CrtpBase class is instantiated and when it isn't.
At point (2), when I call foo(), to my point of view, the compiler should generate a list of possible overloads. These are to be Child::foo() and Child::_Parent::foo(). Therefore Child::_Parent::foo() has to be instantiated. (At this point compilation should fail since the error is in the body function, SFINAE not applicable) Then the compiler should choose the priority match.
However the program compiles and shows that CrtpBase::foo is not instantiated. The question is why. The compiler somehow knows that Child::foo would be the best match and stops overload resolution process.
When I uncomment // using ... , asking compiler explicitly to use base function overload to be one of the matches, nothing changes, it compiles again
Just to make a sort of conclusion of what I have understood from the answers below as they cover different aspects of what's going on
The compiler doesn't even consider the base overload. That is the crucial fact that I didn't see, hence all the misunderstanding
That is not the case here, but choosing the best match during the overload resolution instantiates only the chosen match
At point (2), when I call foo(), to my point of view, the compiler should generate a list of possible overloads.
Trueish. We start by looking up the name foo in Child. We find Child::foo and then stop. We only have one candidate, which is a viable candidate, so we call it. We don't continue to look in the base classes, so CrtpBase::foo is never considered. This is true regardless of signatures (if CrtpBase::foo() took an int, obj.foo(4) would fail to compile because Child::foo() doesn't take an argument - even if a hypothetical call to CrtpBase::foo(4) would be well formed).
When I uncomment // using ..., asking compiler explicitly to use base function overload to be one of the matches, nothing changes, it compiles again
That's actually not what you're doing. The using-declaration brings the name CrtpBase::foo into the scope of Child, as if it were declared there. But then the declaration of void foo() hides that overload (otherwise the call would be ambiguous). So again, name lookup for foo in Child finds Child::foo and stops. Where this case differs from the previous case is if CrtpBase::foo() took different arguments, then it would be considered (such as my hyptohetical obj.foo(4) call in the previous paragraph).
Template classes instances can be instantiated without their methods being instantiated.
Child is not a template class instance. Its methods are always instantiated.
Simply doing overload resolution on a template class instance method name does not trigger template class method instantiation. If it not chosen, it is not instantiated.
This feature originally added in the prehistory of C++. It permitted std::vector<T> to have an operator< that would conditionally work depending on if T had an operator< in the pre-SFINAE era of C++.
For a simpler case:
template<class T>
struct hello {
void foo() { T t{}; t -= 2; }
void foo(std::string c) { T t{}; t += c; }
};
Live example.
Calling hello<int>.foo() considers hello::foo(std::string) and does not instantiate it.
Calling hello<std::string>.foo("world"); considers hello::foo() and does not instanitate it.
I have a class containing several very similar functions and a couple other functions that take those interchangeably functions as input.
A simpler example:
class functions{
public:
int a();
int b();
int F(int (*f)() ); //f can only be a() or b()
};
Before I put them in a class, I had something like
if(f!=a || f!=b) cout<<"error";
With the class, it seems to just get more complicated, since I believe I now need to pass a class instance or something to get rid of my error: invalid use of member function
I have just started to learn about enumerated lists, and it seems like that would do the job if I was dealing with normal variables. Can I create an enum of functions?
What is the best way to restrict functions that can be passed to another function?
I'm pursuing the static cast method, but still needing help with int F( int(*f)() );
int functions::F(int (functions::*f)() )
{
if(f==functions::a)
//gives error: invalid operands of types 'int (functions::*)()'
// and 'int (int(*)()' to binary operator =='
int x=f();
//gives error: must use ‘.*’ or ‘->*’ to call pointer-to-member
//function in 'f(...)'
int y=(functions.*f)();
//gives error: expected primary-expression before ‘.*’ token
return 0;
}
It really depends on what you want to achieve:
I'd say largely that this sort of restriction is best validated by code review rather than coding...
The other solution is to not use that construct at all, and making a Fa() and Fb() function that calls the (private) a() and b() member functions.
And the remainder of the question is "how do I call a member function of a class" -the answer to which depends highly on whether Functions has member variables that are used in a() and b() or not. If there are no member functions, then declaring the a() and b() members as static will work. On the other hand, if you want to use a "member function pointer", the syntax is int (Functions::*f) and &Functions::a respectively, and the call has to be made using an instance of Functions. so if we have Functions fun, you'd do fun.*f(). Or (*this).*f(), insice F().
You may wrap the accepted function in a class:
#include <iostream>
class Functions
{
public:
int a() { return 0; }
int b() { return 1; }
};
class Accept
{
public:
typedef int (Functions::*AcceptFunction)();
int apply(Functions& object, AcceptFunction function) {
return (object.*function)();
}
};
int main()
{
Functions functions;
Accept accept;
std::cout << accept.apply(functions, &Functions::b) << std::endl;
}
(Feel free to bundle it by making Functions a nested class in Accept)
Say i have the following class :
class A
{
public:
A() {
}
A(int a):_a(a){
}
int _a;
};
And the following function :
void someFunc (A a)
{
cout << a._a;
}
So the following line in the program works fine :
someFunc (5); // Calls A(int a) Constructor.
But the following does not :
someFunc(); //Compile error
One can expect that if it can build A when getting an integer,
why not build one using the default constructor as well, when called with no arguments?
Because someFunc() requires an argument and you have not provided an overload which does not. An implicit conversion from int to A exists, but that doesn't mean you can just ignore the function's signature and call it with no arguments. If you would like to call it with no arguments them assign a default value to a.
void someFunc(A a = A()) {
/* stuff */
}
Because you didn't call the function with an argument that turned out to be convertible, you called the function with no arguments. That's a different overload, one you haven't provided.
Consider these options:
Call the function like this: someFunc(A()).
Define a default value for the function parameter: void someFunc (A a = A()) { ... }.
Provide the no-argument overload: void someFunc() { someFunc(A()); }
This is because the signature of someFunc() does not match that of void someFunc (A a).
According to C++ standard, Section 13.3.2.3:
First, to be a viable function, a candidate function shall have enough parameters to agree in number with the arguments in the list.
A candidate function having more than m parameters is viable only if the (m+1)-st parameter has a default argument
None of this applies in this case, so void someFunc (A a) is not considered viable for the invocation with an empty parameter list.
Nitpick. From the 2003 C++ Standard,
17.4.3.2.1 Global names - ...
- Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace
I would tell you that it's poor practice to start any variable name with _. Especially as you may extend that practice into named variable arguments (int foo(int _a)), or do it with camelcase without thinking (int _MyVar). I personally do things like
int a_;
Will you ever actually have trouble? Probably not. But it's good practice not to start your anything with an underscore. Never with two underscores anywhere in the name, or started by an underscore followed by an uppercase letter, of course, too.
I'm not really providing an answer here, but it's useful information all the same... There are times when you really don't want to allow someFunc(5) to work, because it might lead to incorrect operation, or simply be misleading. In such cases you can declare the constructor as explicit:
class A
{
public:
A() {} // Are you sure you don't want to initialise _a here?
explicit A(int a) :_a(a) {}
int _a;
};
And as others have already said you can specify a default parameter for someFunc:
void someFunc( A a = A() );
Now:
someFunc(); // Calls A() by default
someFunc(5); // Not allowed because of implicit construction
someFunc(A(5)); // Caller must pass an instance of A