I am using the gtkmm library on linux to draw a simple menu for my GUI.
In the below code the compiler complained about unable to resolve address
sigc::mem_fun(*this, AppWindow::hide)));
^
appwindow.cpp:15:41: note: could not resolve address from overloaded function
But when I insert the & it compiles fine
m_menu_app.items().push_back(MenuElem("Quit",
sigc::mem_fun(*this, &AppWindow::hide)));
What difference does it make here? Isn't the hide function just an address in the first place?
This is the exact definition of the function-to-pointer conversion, [conv.func]:
An lvalue of function type T can be converted to a prvalue of type
“pointer to T.” The result is a pointer to the function.55
55) This conversion never applies to non-static member functions because an lvalue that refers to a non-static member function
cannot be obtained.
Thus the decay that we see with normal, non-member functions1 doesn't apply and you need to explicitly take the address.
I.e.
void f();
struct A {
void f();
static void g();
};
auto a = f; // Ok: auto deduced as void(*)()
auto b = A::f; // Error: A::f not an lvalue, auto cannot be deduced
auto c = A::g; // Ok: auto deduced as void(*)()
1 Or static member functions.
For global (non-member) functions, the name of the function evaluates to the address of that function except when passed to the & operator, so you can (for example) assign to a pointer to a function either with or without the & equivalently:
int f() {}
int (*pf1)() = f;
int (*pf2)() = &f;
So, in this case there's really no difference between the two.
For member functions1, however, the rules are a bit different. In this case, the & is required; if you attempt to omit the &, the code simply won't compile (assuming a properly functioning compiler, anyway).
There's no particular reason this would have to be the case--it's just how Bjarne decided things should be. If he'd decided he wanted the name of a member function to evaluate to a pointer to a member (equivalent to how things work for non-member functions) he could have done that.
1. Other than static member functions, which mostly act like non-member functions.
When a function is a non-static member function of a class, then it is necessary to use the form &ClassName::functionName when a pointer to the member function is expected in an expression.
When a function is a static member function of a class, both ClassName::functionName and &ClassName;:functionName can be used when a pointer to a function is expected in an expression.
When a function is a global, i.e. non-member, function, both functionName and &functionName can be used when a pointer to a function is expected in an expression.
Related
I have this example about std::function:
int add(int x, int y, int z) {return x + y + z;}
int add(int a, int b) {return a + b;}
int main()
{
std::function<int(int, int)> fn = add; // error
int(*pfn)(int, int) = add; // OK
fn = pfn; // ok fn is bound to add(int, int)
std::cout << fn(5, 7) << std::endl; // 12
}
Why Overload resolution doesn't resolve which version of add when initializing fn but is able to initialize the function pointer pfn?
Is there a workaround rather than using function pointer to decide which version of an overloaded function as an initializer to an std::function object?
Why Overload resolution doesn't resolve which version of add when initializing fn but is able to initialize the function pointer pfn?
Because overload resolution is performed in the initialization of function pointer (like pfn), based on the type of the function pointer.
In all these contexts, the function selected from the overload set is the function whose type matches the pointer to function, reference to function, or pointer to member function type that is expected by target: the object or reference being initialized, the left-hand side of the assignment, function or operator parameter, the return type of a function, the target type of a cast, or the type of the template parameter, respectively.
On the other hand, such overload resolution doesn't happen when initializing a std::function, which has a constructor template and the template parameter needs to be deduced from the function argument; the compiler can't choose one for the deduction.
As the workaround, you can apply static_cast to specify the overload you want explicitly.
static_cast may also be used to disambiguate function overloads by performing a function-to-pointer conversion to specific type
std::function<int(int, int)> fn = static_cast<int(*)(int, int)>(add);
For the function pointer case, C++ has a special rule that permits a sort of "time travelling" lookup. It can perform overload resolution on a name, based on what you're going to assign/initialise the name to.
This is basically a hack built into the language (rules in [over.over]).
No other part of the language works this way. For example, where newcomers often expect that after writing float x = 1/2 the value of x will be 0.5, we have to explain that the fact you're initialising a float has no relevance to the types or calculation of the expression 1/2.
This hack was not extended to std::function. Presumably that is because adding hacks is bad, and because it is not needed for this case. Why not? Because you can still deploy the hack indirectly with a static_cast on the RHS of your std::function initialisation:
std::function<int(int, int)> fn = static_cast<int(*)(int, int)>(add);
… and there's your workaround.
I'm working with std::bind but I still don't get how it works when we use it with member class functions.
If we have the following function:
double my_divide (double x, double y) {return x/y;}
I understand perfectly well the next lines of code:
auto fn_half = std::bind (my_divide,_1,2); // returns x/2
std::cout << fn_half(10) << '\n'; // 5
But now, with the following code where we have a bind to member function I have some questions.
struct Foo {
void print_sum(int n1, int n2)
{
std::cout << n1+n2 << '\n';
}
int data = 10;
};
Foo foo;
auto f = std::bind(&Foo::print_sum, &foo, 95, _1);
f(5);
Why is the first argument a reference? I'd like to get a theoretical explanation.
The second argument is a reference to the object and it's for me the most complicated part to understand. I think it's because std::bind needs a context, am I right? Is always like this? Has std::bind some sort of implementation to require a reference when the first argument is a member function?
When you say "the first argument is a reference" you surely meant to say "the first argument is a pointer": the & operator takes the address of an object, yielding a pointer.
Before answering this question, let's briefly step back and look at your first use of std::bind() when you use
std::bind(my_divide, 2, 2)
you provide a function. When a function is passed anywhere it decays into a pointer. The above expression is equivalent to this one, explicitly taking the address
std::bind(&my_divide, 2, 2)
The first argument to std::bind() is an object identifying how to call a function. In the above case it is a pointer to function with type double(*)(double, double). Any other callable object with a suitable function call operator would do, too.
Since member functions are quite common, std::bind() provides support for dealing with pointer to member functions. When you use &print_sum you just get a pointer to a member function, i.e., an entity of type void (Foo::*)(int, int). While function names implicitly decay to pointers to functions, i.e., the & can be omitted, the same is not true for member functions (or data members, for that matter): to get a pointer to a member function it is necessary to use the &.
Note that a pointer to member is specific to a class but it can be used with any object that class. That is, it is independent of any particular object. C++ doesn't have a direct way to get a member function directly bound to an object (I think in C# you can obtain functions directly bound to an object by using an object with an applied member name; however, it is 10+ years since I last programmed a bit of C#).
Internally, std::bind() detects that a pointer to a member function is passed and most likely turns it into a callable objects, e.g., by use std::mem_fn() with its first argument. Since a non-static member function needs an object, the first argument to the resolution callable object is either a reference or a [smart] pointer to an object of the appropriate class.
To use a pointer to member function an object is needed. When using a pointer to member with std::bind() the second argument to std::bind() correspondingly needs to specify when the object is coming from. In your example
std::bind(&Foo::print_sum, &foo, 95, _1)
the resulting callable object uses &foo, i.e., a pointer to foo (of type Foo*) as the object. std::bind() is smart enough to use anything which looks like a pointer, anything convertible to a reference of the appropriate type (like std::reference_wrapper<Foo>), or a [copy] of an object as the object when the first argument is a pointer to member.
I suspect, you have never seen a pointer to member - otherwise it would be quite clear. Here is a simple example:
#include <iostream>
struct Foo {
int value;
void f() { std::cout << "f(" << this->value << ")\n"; }
void g() { std::cout << "g(" << this->value << ")\n"; }
};
void apply(Foo* foo1, Foo* foo2, void (Foo::*fun)()) {
(foo1->*fun)(); // call fun on the object foo1
(foo2->*fun)(); // call fun on the object foo2
}
int main() {
Foo foo1{1};
Foo foo2{2};
apply(&foo1, &foo2, &Foo::f);
apply(&foo1, &foo2, &Foo::g);
}
The function apply() simply gets two pointers to Foo objects and a pointer to a member function. It calls the member function pointed to with each of the objects. This funny ->* operator is applying a pointer to a member to a pointer to an object. There is also a .* operator which applies a pointer to a member to an object (or, as they behave just like objects, a reference to an object). Since a pointer to a member function needs an object, it is necessary to use this operator which asks for an object. Internally, std::bind() arranges the same to happen.
When apply() is called with the two pointers and &Foo::f it behaves exactly the same as if the member f() would be called on the respective objects. Likewise when calling apply() with the two pointers and &Foo::g it behaves exactly the same as if the member g() would be called on the respective objects (the semantic behavior is the same but the compiler is likely to have a much harder time inlining functions and typically fails doing so when pointers to members are involved).
From std::bind docs:
bind( F&& f, Args&&... args ); where f is a Callable, in your case that is a pointer to member function. This kind of pointers has some special syntax compared to pointers to usual functions:
typedef void (Foo::*FooMemberPtr)(int, int);
// obtain the pointer to a member function
FooMemberPtr a = &Foo::print_sum; //instead of just a = my_divide
// use it
(foo.*a)(1, 2) //instead of a(1, 2)
std::bind(and std::invoke in general) covers all these cases in a uniform way. If f is a pointer-to-member of Foo, then the first Arg provided to bind is expected to be an instance of Foo (bind(&Foo::print_sum, foo, ...) also works, but foo is copied) or a pointer to Foo, like in example you had.
Here is some more reading about pointers to members, and 1 and 2 gives full information about what bind expects and how it invokes stored function.
You also can use lambdas instead std::bind, which could be more clear:
auto f = [&](int n) { return foo.print_sum(95, n); }
Do these lines mean the same? Both works without any warning messages!
int (*pFunc)() = func1; // I learned this is right.
int (*pFunc)() = &func1; // Works well with an ampersand too.
Why do I have to put an ampersand in this case? Without it, doesn't work!
int (CMyClass::*pMemberFunc)() = &CMyClass::memberFunc1;
Why do I have to specify namespace for functions in Classes even if the type of the function pointer matches exactly?
int (*pMemberFunc)() = CMyClass::memberFunc1; // Compiler error
int (*pMemberFunc)() = &CMyClass::memberFunc1; // Compiler error
Why can't I specify namespace in this case?
namespace myNamespace {
int func1() {}
}
int (myNamespace::*pFunc)() = myNamespace::func1; // Compiler error
int (myNamespace::*pFunc)() = &myNamespace::func1; // Compiler error
int (*pFunc)() = &myNamespace::func1; // Works!
Your first question, legalese of the Standard:
A pointer to member is only formed when an explicit & is used and its operand is a qualified-id not enclosed
in parentheses. [Note: that is, the expression &(qualified-id), where the qualified-id is enclosed in
parentheses, does not form an expression of type “pointer to member.” Neither does qualified-id, because
there is no implicit conversion from a qualified-id for a non-static member function to the type “pointer to
member function” as there is from an lvalue of function type to the type “pointer to function” (4.3). Nor is
&unqualified-id a pointer to member, even within the scope of the unqualified-id’s class. —end note ]
While it seems inconsistent at first, I do like the fact that it makes the semantics for pointers to members (be them functions or not) equivalent. This certainly has benefits when dealing with templates and decltype.
For the second question, you scope the pointer variable with CMyClass because yours is not a simple "() -> int" function: memberFunc1() is implicitly passed a CmyClass* argument you normally refer to as "this".
If you could truly pass nothing, you'd be missing information (and possibly crash) for the method to do its job correctly. If you're accustomed to "delegates" in other languages, do remember these can optionally store a "Target" pointer to the "this" object if the method is not static/global.
As for the third, it's a free standing function, so it's truly () -> int, but you're attempting to scope your pointer to the namespace, when in fact you're not declaring your variable inside the namespace block.
While the namespace certainly alters how symbols are searched for, it doesn't affect the convention call of the function at all.
1) about Q1, looking at the following code, as the func1 is a right-value of the function, so with or without "&" doesn't change the actual function address.
Look at the following code:
#include <stdio.h>
void foo(){
printf("foo called\n");
}
int main(){
printf("%p\n", foo);
printf("%p\n", &foo);
void (*FUNC) ();
FUNC = foo;
FUNC();
printf("address %p\n", FUNC);
printf("address %p\n", &FUNC);
return 0;
}
output is
0x101406eb0
0x101406eb0
foo called
address 0x101406eb0
address 0x7fff5e7f9a80
Q2 & Q3 )
Pointers to Member Functions Are Not Pointers
You can refer it here
https://www.safaribooksonline.com/library/view/c-common-knowledge/0321321928/ch16.html
I have seen a code portion in the boost example which is used to construct a state machine. What confused me is the two member functions ElapsedTime()? Is this allowed for the two functions to have the same signatures such as function name and parameters type?
I have googled a lot but without any luck to find relevant info about this. Any advice on this would be greatly appreciated.
struct Active : sc::simple_state< Active, StopWatch, Stopped >
{
public:
typedef sc::transition< EvReset, Active > reactions;
Active() : elapsedTime_( 0.0 ) {}
double ElapsedTime() const { return elapsedTime_; }
double & ElapsedTime() { return elapsedTime_; }
private:
double elapsedTime_;
};
Signature of a function is defined by the name and by the argument types.
You have two functions with the same name, but they do not get the same arguments!
You might wonder how could it be?
So, each member function gets another parameter implicitly: this is the "this" pointer. A pointer to the object who called that method.
When you add const in the end of the method, you specify the "this" argument as a const pointer to const. In the other method (without the const), the type of "this" is just const pointer.
Hence, you have two methods with different signature, and there is no problem at all.
They do not have the same signatures - one is const and another one is not. Constness is part of member function signature.
The signatures are different because one has const qualifier.
http://www.cprogramming.com/tutorial/const_correctness.html
Is this allowed
This usage is allowed as over.load#2.2 states:
Member function declarations with the same name and the same parameter-type-list cannot be overloaded if any of them is a static member function declaration ([class.static]). Likewise, member function template declarations with the same name, the same parameter-type-list, and the same template parameter lists cannot be overloaded if any of them is a static member function template declaration. The types of the implicit object parameters constructed for the member functions for the purpose of overload resolution ([over.match.funcs]) are not considered when comparing parameter-type-lists for enforcement of this rule. In contrast, if there is no static member function declaration among a set of member function declarations with the same name and the same parameter-type-list, then these member function declarations can be overloaded if they differ in the type of their implicit object parameter. [ Example: The following illustrates this distinction:
(end quote)
Now, in your example the first overload has a const qualifer which means that its implicit object parameter has type const Active& while the second overload has no const qualifer meaning that its implicit object parameter is of type Active&. Moroever, there is no static member function declaration for ElapsedTime with the same paremeer-type-list. Hence using the above quoted statement, this means that the given usage is allowed.
Note
Note that the currently accepted answer is technically incorrect because it claims that this is a const pointer to const. But in reality the standard specifies that inside a const qualified member function the this pointer is of type const X* while inside a non-const qualified member function the this pointer is of type X*.
The following code:
struct X
{
void f() {}
void g()
{
auto h = &f;
}
};
results in:
error: ISO C++ forbids taking the address of an unqualified
or parenthesized non-static member function to form a pointer
to member function. Say ‘&X::f’
My question is, why is this not allowed and forbidden by the standard? It would be more convenient as a user to refer to it unqualified, so I assume there is some other rationale (safety? an ambiguity? ease of compiler implementation?) for the requirement?
pointer-to-member is rare enough to allow special treatment and not necessarily the most economic one. It was decided that the only accepted form is the one quoted in the error message. That form does not clash with anything else under any circumstances. And prevents ambiguity of more lax forms were allowed.
Practice shows little awareness of PTMFs, and the fact they fundamentally differ from functions. f or &f is likely a request for a normal function. One that can't be served for a nonstatic member. And those who actually mean PTMF say so adding the &X:: part.
You're taking the address of a member function, not a function, and that means you will have to call it differently, too.
struct X
{
void f() {}
void g()
{
auto h = &X::f;
h();
}
};
Produces:
error: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘h (...)’, e.g. ‘(... ->* h) (...)’