How do parentheses around the function name change which function is called? - c++

I could not understand the second foo call in the code below. How does it call global foo function. Why does (foo) call struct A's int()? Can you help me?
#include <stdio.h>
#include <utility>
#include <iostream>
using namespace std;
namespace MySpace{
struct A{
operator int () const {
cout <<"operator" << endl;
return 1;
}
};
void foo(A){
std::cout<< "1" << endl;
}
}
void foo(int){
std::cout << "--2" << endl;
}
int main()
{
MySpace::A x;
foo(x);
(foo)(x);
return 0;
}
I could not understand the second foo call. How does it call global foo function. Why does (foo) call struct A's int()? Can you help me?

The 1st one works because ADL finds MySpace::foo and it wins in overload resolution against ::foo and gets called.
For the 2nd one, adding parentheses like (foo) prevents ADL; then MySpace::foo can't be found, only ::foo is found and gets called. A is converted to int implicitly (by A's conversion operator) for it to be called.
BTW: You can mark the conversion operator as explicit to forbid the implicit conversion from A to int. Then the 2nd one would fail. E.g.
namespace MySpace {
struct A{
explicit operator int () const {
cout <<"operator" << endl;
return 1;
}
};
void foo(A){
std::cout<< "1" << endl;
}
}

Related

Overload resolution in nested namespace with parent namespace

I thought that in a nested namespace, anything that is part of the parent (or global) namespace is considered equally for overload resolution, but this example seems to show otherwise.
This works fine:
#include <iostream>
void foo(int) { std::cout << "int\n"; }
void foo(float) { std::cout << "float\n"; }
namespace NS {
void bar() {
foo(0);
}
}
int main() {
NS::bar();
}
The call to foo(0) matches foo(int) since it is a better match and everything works as expected. However, if I move the declaration of foo(float) into the namespace:
#include <iostream>
void foo(int) { std::cout << "int\n"; }
namespace NS {
void foo(float) { std::cout << "float\n"; }
void bar() {
foo(0);
}
}
int main() {
NS::bar();
}
The call to foo(0) now calls foo(float)!
I have searched through https://en.cppreference.com/w/cpp/language/overload_resolution and many other such pages to find the rule that explains this, but I seem to be missing it. Can someone please explain which of the many complex overload resolution rules causes this, or is it something else?
EDIT
I just discovered it is even weirder. Even if the foo inside the namespace doesn't match at all, it still won't use the one outside. This just completely fails to compile:
#include <iostream>
void foo(int) { std::cout << "int\n"; }
namespace NS {
void foo(float, float) { std::cout << "float\n"; }
void bar() {
foo(0);
}
}
int main() {
NS::bar();
}
The point is name lookup, which happens before overload resolution.
When the name foo is found at the namespace NS, name lookup stops, the further scopes won't be checked, the global foo won't be found at all. Then there's only one candidate in overload resolution, and int could convert to float implicitly, then NS::foo(float) gets called at last.
(emphasis mine)
name lookup examines the scopes as described below, until it finds at least one declaration of any kind, at which time the lookup stops and no further scopes are examined.

Declaration of the function pointer

What do I declare with the following definition:
void (*bar)(A*){ }; //1
My first thought was that I declare and define function pointer and a function the pointer point to. But it's wrong, because any call to the bar() leads to a segmentation fault:
#include <iostream>
#include <vector>
#include <memory>
struct A{ };
void foo(A*){ std:cout << "foo" << std::endl; }
void (*bar)(){ };
int main(){
bar();
}
Moreover, I can't imbed any statement into the "definition":
void (*bar)(A*){ std::cout << "foo" << std::endl };
yeilds compile-time error.
So, what does the declaration //1 mean?
This statement:
void (*bar)(A*){ };
declares a variable named bar of type void(*)(A*), ie "pointer to function taking pointer to A and returning void", and zero-initializes it. Thus, it's equivalent to this:
void (*bar)(A*) = nullptr;
Obviously, when calling this bar, a segfault should be no surprise.
It's not possible to declare a function and a pointer to that function in a single declaration.
When you say
void (*bar)(A*){ }; //1
it means "bar" is a function pointer which can point to some function which takes "A*" as parameter.
In your case, it is not pointing to any function yet.
to make it working use,
void (*bar)(A*) = foo;
This means you have declared a function pointer that points to nothing at the moment. You should able to validate that using a debugger.
void (*bar)(A*){ }; //1
You could make the pointer point to a function like this:
void foo(A*){ std::cout << "foo" << std::endl };
bar = &foo;
And call it like this now:
A a;
bar(&a);
Full snippet:
#include <iostream>
class A {};
void (*bar)(A*){};
void foo(A*) { std::cout << " foo " << std::endl;}
int main() {
A a;
bar = &foo;
bar(&a);
}
Your code should be changed to the following code.
#include <iostream>
#include <vector>
#include <memory>
struct A{ };
void foo(A*){ std::cout << "foo" << std::endl; }
void (*bar)(A*);
int main(){
A a;
bar = &foo;
bar(&a);
}
To declare an actual function, get rid of the (*) portion around the function name:
void bar(A*){ std::cout << "foo" << std::endl };
https://ideone.com/UPIYxg
So, what does the declaration //1 mean?
It is just a comment.

Why can't we call a function from a function with a default argument?

The program:
#include <iostream>
void foo(void (*bar)()){ bar(); };
void foo(int a = 5)
{
std::cout << a << std::endl;
}
int main()
{
foo(foo); //Error
}
DEMO
I expected that eventually foo(5) will be called. In contrast, the following program works fine:
#include <iostream>
void foo(void (*bar)()){ bar(); };
void foo()
{
std::cout << 5 << std::endl;
}
int main()
{
foo(foo); //OK
}
DEMO
Could you explain that difference?
In the first example although foo has default argument its type is void (bar*)(int). Having the default argument makes it possible to call foo without specifying the argument value explicitly, but there is still an int argument. Simply its value is automatically populated(during compilation).

Overload for std::string not detected in template code

I'm writing some template code to determine if a given type can be passed as any argument to any available overload of a function. In the example below I've used the log function, but I've also tried this code on others in the math library, and the results are the same. The idea is to use function overloading and the sizeof operator to distinguish between cases where the type in question can legally be passed to the function in question (log, in this example).
If it worked, we'd have sizeof(overload<type>(NULL)) == sizeof(True) when 'type' can be legally passed to log, and sizeof(overload<type>(NULL)) == sizeof(False) otherwise. This does seems to work for most types, but fails for std::string.
Here's exactly how it fails:
Under normal circumstances we have sizeof(overload<std::string>(NULL)) == sizeof(False), as we should. But, when I declare an overload of log that does take a string, it still doesn't trigger the sizeof(True) branch of the logic. Note that I don't actually want to declare log(std::string) function, I'm just testing this code to make sure that it's able to detect all possible overloads.
At first I thought it just wasn't detecting overloads properly, but when I tried it with a user-defined class ('MyClass' in the example below), it worked fine: it produced sizeof(True) when log(MyClass) was declared, and sizeof(False) otherwise.
#include <iostream>
#include <math.h>
template<int>
struct TakesInt{};
struct True
{
};
struct False
{
// guarantees that sizeof(False) != sizeof(True)
True array[2];
};
// takes anything; fall back if no match can be found
template<typename T>
False overload(...);
// takes a specific type; does not actually call log
template<typename T>
True overload(TakesInt<sizeof(log(T()))>*);
// As a test, this is an overload of log that takes a string.
// I don't actually want to implement this, but it should make the compiler
// think that a string is a valid argument.
double log(std::string);
// a placeholder for user defined class; could really be anything,
// like an arbitrary number class
struct MyClass{};
// declaring log for the arbitrary class above
// note that this is the same as for the log(std::string)
// if one works, the other should
double log(MyClass);
int main()
{
std::cout << sizeof(True) << '\t' << sizeof(False) << std::endl;
std::cout << sizeof(overload<std::string>(NULL)) << std::endl;
std::cout << sizeof(overload<double>(NULL)) << std::endl;
std::cout << sizeof(overload<MyClass >(NULL)) << std::endl;
return 0;
}
Here's the same issue w/o the SFINAE distraction:
#include <iostream>
namespace ns
{
struct string {};
}
void bar(...) { std::cout << "void bar(...)\n"; }
template<class T>
void foo()
{
T x{};
bar(x);
}
void bar(ns::string) { std::cout << "void bar(ns::string)\n"; }
int main()
{
foo<int>();
foo<ns::string>();
}
Output:
void bar(...)
void bar(...)
Lookup of a dependent function name will be performed:
as (pure) unqualified lookup from the point of definition
as (pure) argument-dependent lookup from the point of instantiation
Therefore, the following example differs:
#include <iostream>
namespace ns
{
struct string {};
}
void bar(...) { std::cout << "void bar(...)\n"; }
template<class T>
void foo()
{
T x{};
bar(x);
}
namespace ns
{
void bar(ns::string) { std::cout << "void bar(ns::string)\n"; }
}
int main()
{
foo<int>();
foo<ns::string>();
}
Output:
void bar(...)
void bar(ns::string)
For std::string, the only associated namespace is std. The global namespace is not associated and will not be searched in the OP's code. Therefore, the overload declared after the template definition will not be found.
N.B. Please do not inject overloads into namespace std. This will lead to undefined behaviour as per [namespace.std]/1.

C++ Syntax to call a member function using it's function pointer

The example below uses a function pointer to a member function of the class Blah. The syntax of the function pointer is clear to me. However when calling I had to put brackets around this->*funcPtr and I am not sure why this is required. I guess it is related to the way how C++ evaluates the expression. The compiler used is VS 2008.
#include <iostream>
using namespace std;
struct Blah {
void myMethod(int i, int k) {
cout << "Hi from myMethod. Arguments: " << i << " " << k << endl;
}
typedef void (Blah::*blahFuncPtr)(int, int);
void travelSomething(blahFuncPtr funcPtr) {
(this->*funcPtr)(1, 2);
// w/o the brackets I get C2064 in VS 2008
// this->*funcPtr(1, 2);
}
};
int main() {
Blah blah;
blah.travelSomething(&Blah::myMethod);
cin.get();
return 0;
}
The function call operator () takes higher precendence than the 'pointer to member' operator ->*.
See, for example, here.