My question is about using std::function to class methods. Suppose I have the following class hierarchy:
class Foo {
public:
virtual void print() {
cout << "In Foo::print()" << endl;
}
virtual void print(int) {
cout << "In Foo::print(int)" << endl;
}
};
class Bar : public Foo {
public:
virtual void print() override {
cout << "In Bar::print()" << endl;
}
virtual void print(int) override {
cout << "In Bar::print(int)" << endl;
}
}
Now there is another function which is supposed to dynamically call one of the two class methods depends on its input:
void call(Foo* foo, void (Foo::*func)(void)) {
(foo->*func)();
}
Foo* foo = new Foo();
Bar* bar = new Bar();
call(foo, &Foo::print);
call(bar, &Foo::print);
When I compile the above code snippet using g++/clang++, it works as expected, where the output is:
In Foo::print()
In Bar::print()
My questions are then:
since there are two functions (overloaded) with the same name: print, when I pass the address of class function: &Foo::print, how did the compiler know that I am actually calling Foo::print(void) but not Foo::print(int)?
is there another way that I can generalize the code above such that the second parameter of void call(Foo*, xxx) can be passed using both Foo::print(void) and Foo::print(int)
is there anyway to achieve this feature using new feature in C++11 std::function ? I understand that in order to use std::function with a non-static class method, I have to use std::bind to bind each class method with a specific class object, but that would be too inefficient for me because I have many class objects to be bound.
Since there are two functions (overloaded) with the same name: print, when I pass the address of class function: &Foo::print, how did the compiler knows that I am actually calling Foo::print(void) but not Foo::print(int)?
This is allowed because of [over.over]/p1:
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a
pointer to function or a pointer to member function for a specific function from the overload set.
The compiler can use the target type of the parameter-type-list to determine which function from the overload set the pointer-to-member refers:
A use of an overloaded function name without arguments is resolved in certain contexts to a function, a
pointer to function or a pointer to member function for a specific function from the overload set. A function
template name is considered to name a set of overloaded functions in such contexts. The function selected
is the one whose type is identical to the function type of the target type required in the context. [ Note: .. ] The target can be
— an object or reference being initialized (8.5, 8.5.3, 8.5.4),
— the left side of an assignment (5.18),
— a parameter of a function (5.2.2),
— [..]
The name Foo:print represents an overload set which the compiler looks through to find a match. The target type Foo::print(void) is present in the overload set, so the compiler resolves the name to that overload.
Is there another way that I can generalize the code above such that the second parameter of void call(Foo*, xxx) can be passed using both Foo::print(void) and Foo::print(int)
There isn't a general way to do it with the name itself. The name has to be resolved to an overload. Instead, try changing the code to accept a function object like a lambda:
template<class Callable>
void call(Foo* foo, Callable&& callback) {
callback(foo);
}
int main()
{
call(foo, [] (Foo* f) { f->print(); f->print(1); });
}
First, std::bind is (almost) entirely outmoded by C++11 lambdas. Don't use std::bind if you can help it. One of these is much clearer than the others, using your example code:
const auto lambda = [=] { foo->print(); }; // Clear!
const auto binderv = std::bind( static_cast<void(Foo::*)()>( &Foo::print ), foo ); // Gets the void version
const auto binderi = std::bind( static_cast<void(Foo::*)(int)>( &Foo::print ), foo, std::placeholders::_1 ); // Gets the int version
//const auto binderv2 = std::bind( &Foo::print, foo ); // Error! Can't tell which Foo::print()
//const auto binderi2 = std::bind( &Foo::print, foo, std::placeholders::_1 ); // Error! Can't tell which Foo::print()
lambda(); // prints "void"
binderv(); // prints "void"
binderi(1); // prints "int"
Second, how does the compiler know which overloaded function to call? The same way it would if you were using non-member functions:
#include <iostream>
void call( void (*fn)() )
{
fn();
}
void print() { std::cout << "void\n"; }
void print(int) { std::cout << "int\n"; }
int main()
{
call( &print ); // prints "void"
}
Only one of those overloaded functions fits the called function's prototype, so the compiler knows. In the case of std::bind above, it can't quite tell, but you can force it with a cast, as I did.
Lambdas or std::function can wrap either of the member functions, but note that you can't overload a function on different std::function signatures. See here.
Update:
The right way to handle your question #3 -- to have one function call functions with drastically different signatures like yours -- is to use some intermediary like a functor (lambda, std::function, std::bind, hand-rolled functor) to erase the differences.
std::function<void()> objects that have the same signature, regardless of what the real functions you're calling have as their signature. std::function is more expensive (in terms of storing and calling) than a lambda but it has the advantage of having a typename that you can use if you need to store it in a container or something. Lambdas can sometimes be inlined away by the compiler if you play your cards right, so efficiency may still favor lambdas.
Related
In C++, is there a way to define a function that takes N number of random arguments (number and parameter types could be anything) and in that function, instantiates a class who's constructor expects those arguments. In pseudo-code, something like:
class ClassType {
ClassType(int, string){}
};
void func(Args ...) {
ClassType A(Args);
}
And better yet, define a function pointer for "func"
Yes it is possible. Output of this
#include <iostream>
#include <utility>
struct ClassType {
ClassType(int a, std::string b){
std::cout << a << b;
}
};
template <typename...Args>
void func(Args&& ... args) {
ClassType A(std::forward<Args>(args)...);
}
int main() {
func(12,std::string("foo"));
}
is
12foo
However, it isnt quite clear why you want func to be variadic when ClassTypes constructor only accepts int,string. Calling func with any other combination will fail.
And better yet, define a function pointer for "func"
You cannot have a function pointer to a template (you also cannot have a function pointer to a whole set of overloads). Thats not how function pointers work. What you can do is taking a function pointer to one particular instantiation of func:
auto fptr = &func<int,std::string>;
If you need some function like object that you can pass around then you can use a generic lambda instead of a bare function pointer (since C++17 I believe):
auto flamb = [](auto&&...args){ func(std::forward<decltype(args)>(args)...); };
This works because the lambda is of some type (albeit unnamed and unspecified) and only its operator() is templated. Hence you can pass such lambda around and only when actually calling it the respective operator() is instantiated. Though, also with that you can only call it with the right parameters (int and std::string).
The following is a perfectly legal C++ code
void foo (int) {
cout << "Yo!" << endl;
}
int main (int argc, char const *argv[]) {
foo(5);
return 0;
}
I wonder, if there a value to ever leave unnamed parameters in functions, given the fact that they can't be referenced from within the function.
Why is this legal to begin with?
Yes, this is legal. This is useful for implementations of virtuals from the base class in implementations that do not intend on using the corresponding parameter: you must declare the parameter to match the signature of the virtual function in the base class, but you are not planning to use it, so you do not specify the name.
The other common case is when you provide a callback to some library, and you must conform to a signature that the library has established (thanks, Aasmund Eldhuset for bringing this up).
There is also a special case for defining your own post-increment and post-decrement operators: they must have a signature with an int parameter, but that parameter is always unused. This convention is bordering on a hack in the language design, though.
Of course not naming a parameter is legal when just declaring the function, but it's also legal in the implementation. This last apparently strange version is useful when the function needs to declare the parameter to have a specific fixed signature, but the parameter is not needed.
This may happen for example for a method in a derived class, for a callback function or for a template parameter.
Not giving the parameter a name makes clear that the parameter is not needed and its value will not be used. Some compilers if you instead name a parameter and then simply don't use it will emit a warning that possibly there is a problem with the function body.
Just wanted to mention a specific (unusual but interesting) usecase - the "passkey idiom".
It uses a "dummy" parameter of a type, constructor of which is accessible only to its friends. Its purpose is only to check, whether the caller has access to this constructor. So it needs no name as it is not used in the function, only the compiler uses it.
It's used like this:
class Friendly; // Just a forward declaration
class Key {
private:
Key() {}
friend class Friendly;
};
class Safe() {
public:
static int locked(Key, int i) {
// Do something with `i`,
// but the key is never used.
return i;
}
private:
static void inaccessible() {}
};
class Friendly {
public:
void foo() {
int i = Safe::locked(Key(), 1); // OK
int j = Safe::locked({}, 2); // OK, sice C++11
}
void bar() {
Safe::inaccessible(); // Not OK, its inaccessible
}
};
int i = Safe::locked(3); // Not OK, wrong parameters
int j = Safe::locked(Key(), 4); // Not OK, `Key` constructor is inaccessible
int k = Safe::locked({}, 5); // Not OK, `{}` means `Key()` implicitly
I just want to add that there is sometimes a difference whether you name a parameter or not. For example, the compiler treats a named rvalue reference as an lvalue and an unnamed rvalue reference as an rvalue.
// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
// A class that contains a memory resource.
class MemoryBlock
{
// TODO: Add resources for the class here.
};
void g(const MemoryBlock&)
{
cout << "In g(const MemoryBlock&)." << endl;
}
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
MemoryBlock&& f(MemoryBlock&& block)
{
g(block);
return block;
}
int main()
{
g(f(MemoryBlock()));
}
This example produces the following output:
In g(const MemoryBlock&).
In g(MemoryBlock&&).
In this example, the main function passes an rvalue to f. The body of f treats its named parameter as an lvalue. The call from f to g binds the parameter to an lvalue reference (the first overloaded version of g).
I need to use a function defined in one class in another class. Instead of rewriting the whole function, I tried to pass the function as a pointer, as below:
class C {
public:
int get(int x) { return x*x; }
};
struct S {
int (*func) (int x);
};
int main() {
C c;
S s;
cout << c.get(3) << endl;
s.func = &C::get;
cout << s.func(3) << endl;
return 0;
}
This doesn't work and gives the following error:
func_ptr.cpp: In function ‘int main()’:
func_ptr.cpp:42:18: error: cannot convert ‘int (C::*)(int)’ to ‘int (*)(int)’ in assignment
Is it possible to do something like this, and if so, how can I fix it? Moreover, if it is possible, can I use the pointer from an object instance instead of the class? That is, to possibly use variables defined in a specific class instance. Thanks.
C::get() is a non-static member function, which means it must be invoked on an instance of C. It has an implicit first argument, the this pointer, that must be passed to it when calling the function.
Since your C::get() doesn't seem to need access to any data members of C, you could make it a static member function.
static int get(int x) { return x*x; }
Now your code will work as is.
Another option is to change func so that it is a pointer to a member function of C
struct S {
int (C::*func) (int x);
};
And invoke it as
s.func = &C::get;
std::cout << (c.*(s.func))(3) << std::endl;
Yet another option would be to change the type of S::func to std::function<int(int)>. Now it can hold any callable (function pointer, functor, lambda) that takes a single int as an argument, and returns an int.
struct S {
std::function<int(int)> func;
};
s.func = std::bind(&C::get, &c, std::placeholders::_1);
std::cout << s.func(3) << std::endl;
A regular function and a member function are a bit different. To use a member function, you'll need an object to call it on (i.e. the this pointer in a member function body).
Take a look at std::function and std::bind, they are used to handle function like (callable) entities in a uniform way. They can manage global functions, static member functions, lambdas, regular member functions, functors, whatever that can be called like a function.
http://en.cppreference.com/w/cpp/utility/functional/function
http://en.cppreference.com/w/cpp/utility/functional/bind
http://en.cppreference.com/w/cpp/header/functional
e.g.:
struct S
{
std::function<int(int)> func;
};
C c;
S s;
s.func = std::bind( &C::get, &c, std::placeholders::_1 );
If you're OK with using STL then you can utilize std::function to hold a pointer to a function and std::bind to bind that particular pointer to a particular function. It makes your code look much more cleaner. std::bind looks for both static and non-static member functions. For non-static member function would need to pass the object reference so it will be able to point to the correct address.
Here is a code snippet to show how to use it:
std::bind(ClassName::MemberFunctionName, object, std::placeholders::_1)
std::placeholders::_1 means that ::MemberFunctionName accepts one parameter.
void someFunction(boost::function<void()> func)
{
... //Get myObj
}
MyClass *myObj = ...;
someFunction(boost::bind(&MyClass::memberFunction, myObj));
How can I get pointer or reference to myObj from inside the function void someFunction
Generally it is not possible nor desirable to extract the object used as an argument to boost::bind (or std::bind) back from the result of the bind. The way the resulting object is stored is implementation specific.
Observe how it is defined as unspecified in the documentation (see link below):
// one argument
template<class R, class F, class A1> unspecified-3 bind(F f, A1 a1);
To illustrate further, take a look at this paragraph, on the same page:
The function objects that are produced by boost::bind do not model the
STL Unary Function or Binary Function concepts, even when the function
objects are unary or binary operations, because the function object
types are missing public typedefs result_type and argument_type or
first_argument_type and second_argument_type. In cases where these
typedefs are desirable, however, the utility functionmake_adaptable
can be used to adapt unary and binary function objects to these
concepts.
http://www.boost.org/doc/libs/1_55_0/libs/bind/bind.html#CommonDefinitions
The library developers explicitly tell you that the type that's returned is opaque, won't give you back the type of the arguments you've passed in, and don't intend for you to obtain the objects from within the opaque bind return type.
However, when you call bind() it is you who supplies the argument, so you can just store them aside and use them later. Alternatively, as suggested in the comments you can just use *this as a reference to the callee when the bound method is invoked.
#include <boost/bind.hpp>
#include <iostream>
struct Foo {
void f() const {
const Foo& myObj = *this;
std::cout << "Invoked instance: " << std::hex << &myObj << std::endl;
}
};
int main() {
Foo foo;
std::cout << "Invoking instance: " << std::hex << &foo << std::endl;
boost::bind(&Foo::f, boost::ref(foo))();
return 0;
}
/* Output:
Invoking instance: 0x7fff4381185f
Invoked instance: 0x7fff4381185f */
The following is a perfectly legal C++ code
void foo (int) {
cout << "Yo!" << endl;
}
int main (int argc, char const *argv[]) {
foo(5);
return 0;
}
I wonder, if there a value to ever leave unnamed parameters in functions, given the fact that they can't be referenced from within the function.
Why is this legal to begin with?
Yes, this is legal. This is useful for implementations of virtuals from the base class in implementations that do not intend on using the corresponding parameter: you must declare the parameter to match the signature of the virtual function in the base class, but you are not planning to use it, so you do not specify the name.
The other common case is when you provide a callback to some library, and you must conform to a signature that the library has established (thanks, Aasmund Eldhuset for bringing this up).
There is also a special case for defining your own post-increment and post-decrement operators: they must have a signature with an int parameter, but that parameter is always unused. This convention is bordering on a hack in the language design, though.
Of course not naming a parameter is legal when just declaring the function, but it's also legal in the implementation. This last apparently strange version is useful when the function needs to declare the parameter to have a specific fixed signature, but the parameter is not needed.
This may happen for example for a method in a derived class, for a callback function or for a template parameter.
Not giving the parameter a name makes clear that the parameter is not needed and its value will not be used. Some compilers if you instead name a parameter and then simply don't use it will emit a warning that possibly there is a problem with the function body.
Just wanted to mention a specific (unusual but interesting) usecase - the "passkey idiom".
It uses a "dummy" parameter of a type, constructor of which is accessible only to its friends. Its purpose is only to check, whether the caller has access to this constructor. So it needs no name as it is not used in the function, only the compiler uses it.
It's used like this:
class Friendly; // Just a forward declaration
class Key {
private:
Key() {}
friend class Friendly;
};
class Safe() {
public:
static int locked(Key, int i) {
// Do something with `i`,
// but the key is never used.
return i;
}
private:
static void inaccessible() {}
};
class Friendly {
public:
void foo() {
int i = Safe::locked(Key(), 1); // OK
int j = Safe::locked({}, 2); // OK, sice C++11
}
void bar() {
Safe::inaccessible(); // Not OK, its inaccessible
}
};
int i = Safe::locked(3); // Not OK, wrong parameters
int j = Safe::locked(Key(), 4); // Not OK, `Key` constructor is inaccessible
int k = Safe::locked({}, 5); // Not OK, `{}` means `Key()` implicitly
I just want to add that there is sometimes a difference whether you name a parameter or not. For example, the compiler treats a named rvalue reference as an lvalue and an unnamed rvalue reference as an rvalue.
// named-reference.cpp
// Compile with: /EHsc
#include <iostream>
using namespace std;
// A class that contains a memory resource.
class MemoryBlock
{
// TODO: Add resources for the class here.
};
void g(const MemoryBlock&)
{
cout << "In g(const MemoryBlock&)." << endl;
}
void g(MemoryBlock&&)
{
cout << "In g(MemoryBlock&&)." << endl;
}
MemoryBlock&& f(MemoryBlock&& block)
{
g(block);
return block;
}
int main()
{
g(f(MemoryBlock()));
}
This example produces the following output:
In g(const MemoryBlock&).
In g(MemoryBlock&&).
In this example, the main function passes an rvalue to f. The body of f treats its named parameter as an lvalue. The call from f to g binds the parameter to an lvalue reference (the first overloaded version of g).