Make a free function behave like a member function (C++) - c++

Assuming I have a function like the following in C++:
template<typename Container>
void doNothing(Container * container) {
for (auto element: container) {
std::cout << element;
}
}
Would it be possible to "simulate" methods on various classes that could implement this function by passing this to it instead of the first parameter. (E.g. a class like std::vector, std::string ... etc).
So basically instead of having to use it as:
std::vector<double> a{1, 2, 0.5}:
doNothing(a);
I could call it as:
std::vector<double> a{1, 2, 0.5}:
a.doNothing();

No, you can't do that.
The this parameter in the call a.b() is implicit, and there's no way to fake an implicit parameter.
The a.b() syntax is simply not available to you unless b is a member.

You can always simulate a member function by passing the this pointer of an object.
After all, that's all the compiler is doing for proper member functions (passing this as a hidden first parameter).
So, if you want a function foo to behave like a member and operate on an object (ignoring private/protected here) of type Bar, then you could declare it as:
void foo(Bar* self);
and call it like
Bar b;
foo(&b);
(or from inside a Bar member: foo(this);)
then it would be able to access members of b and call its functions by dereferencing the self pointer.

template<class F>
struct poly_mem_ptr_t{
F f;
template<class T>
friend auto operator->*( T* t, poly_mem_ptr_t self )const{
return
[t, f=self.f](auto&&...args)->decltype(auto){
return f(t, decltype(args)(args)...);
};
}
template<class T>
friend auto operator->*( T& t, poly_mem_ptr_t self )const{
return std::addressof(t)->*self;
}
};
template<class F>
poly_mem_ptr_t<F> poly_mem_ptr(F f){ return {std::move(f)}; }
Sample use:
auto do_nothing = poly_mem_ptr([](auto* ptr){ doNothing(ptr); });
std::vector<int> v={1,2,3};
(v->*do_nothing)();
not exactly what you want, but close.
As a benefit, you can add
template<class...Ts>
friend decltype(auto) operator->*( std::variant<Ts...>& var, poly_mem_ptr_t self )const{
return [&var, f=self.f](auto&&...args) {
return std::visit( [&](auto&&t)->decltype(auto){
return f( decltype(t)(t), decltype(args)(args)... );
}, var);
};
}
and now you can take a std::variant and use these poly_mem_ptrs as visitors.
With a bit of work you can also tool up an augmented std::any to support a fixed set of poly_mem_ptrs.

Related

Function pointer overloading using typedef

As I understand, typedef cannot be used for overloading but what if I need to use some different types as arguments to the function pointer?
How can I make it work with the following functionality?
{
public:
typedef void (*InitFunc)(float x);
typedef void (*InitFunc)(int a, char b); //Needs to be added
virtual void initialize(InitFunc init) = 0;
};
Edit:
I cannot use C++17, so can't use variant
As commented, the easiest way is a union, although not very type safe and C++-y. Here is an example with inheritance, since you commented that you want inheritance.
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
union InitFn {
FloatInit fi;
IntCharInit ici;
};
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
f.fi(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
As mentioned by other commenters, you can use std::variant to enhance type safety and get rid of the manual union definition:
typedef void (*FloatInit)(float x);
typedef void (*IntCharInit)(int a, char b);
typedef std::variant<FloatInit, IntCharInit> InitFn;
struct Foo {
void initialize(InitFn) = 0;
};
struct FloatFoo: public Foo {
void initialize(InitFn f) override {
std::get<FloatInit>(f)(42.0f);
}
};
void test(float) {}
// ...
auto x = FloatFoo{};
x.initialize(InitFn{test});
One solution is to create a simple wrapper class template instead, to allow the compiler to automatically generate instantiations as necessary. This is relatively simple if init is always guaranteed to be a non-member function (and by extension, an actual function and not a functor/lambda).
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> {
public:
// Supply component types if needed.
// Tuple used for params, for convenience.
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
// Create from pointer or reference.
constexpr InitFunc(func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator func_ptr_type() { return ptr; }
operator func_ref_type() { return *ptr; }
private:
// Actual function pointer.
func_ptr_type ptr;
};
// And a nice, clean creator, which can be renamed as necessary.
template<typename Init>
constexpr auto make(Init func) { return InitFunc<Init>(func); }
This creates a nice little wrapper that can easily be optimised out entirely, and will compile as long as C++14 support is available.
Note that you require a C++11 compiler (or variadic templates, rvalue references, perfect forwarding, and constexpr support) at the absolute minimum, and will need to modify make() to have a trailing return type for pre-C++14 compilers. I believe this is compatible with C++11 constexpr, but I'm not 100% sure.
If you want InitFunc to be able to accept pointers/references-to-member-function (including functors and lambdas), you'll need to provide an additional version to isolate it into a non-member "function", and likely bind it to a class instance. It may be worth looking into std::bind() in this case, although I'm not sure if it has any overhead.
In this case, I would suggest splitting the member types off into a base class, to reduce the amount of code you'll need to duplicate.
// Quick-and-dirty transparent callable wrapper, to serve as overloadable "type alias".
template<typename>
class InitFunc;
// Supply component types if needed.
// Tuple used for params, for convenience.
// Using actual function type as a base, similar to std::function.
template<typename Ret, typename... Params>
class InitFunc<Ret(Params...)> {
public:
using return_type = Ret;
using param_types = std::tuple<Params...>;
using func_type = Ret(Params...);
using func_ptr_type = func_type*;
using func_ref_type = func_type&;
};
// Non-member functions.
// As member types are now dependent types, we qualify them and use `typename`.
// Yes, it looks just as silly as you think it does.
template<typename Ret, typename... Params>
class InitFunc<Ret(*)(Params...)> : public InitFunc<Ret(Params...)> {
// Actual function pointer.
typename InitFunc::func_ptr_type ptr;
public:
// Create from pointer or reference.
constexpr InitFunc(typename InitFunc::func_ptr_type p = nullptr) : ptr(p) {}
constexpr InitFunc(typename InitFunc::func_ref_type r) : ptr(&r) {}
// Transparent invocation.
// Deduces argument types instead of relying on Params, to allow for perfect forwarding.
template<typename... Ts>
constexpr typename InitFunc::return_type operator()(Ts&&... ts) { return ptr(std::forward<Ts>(ts)...); }
// Convert back to original type if necessary.
operator typename InitFunc::func_ptr_type() { return ptr; }
operator typename InitFunc::func_ref_type() { return *ptr; }
};
// See ecatmur's http://stackoverflow.com/a/13359520/5386374 for how to accomodate member functions.
// ...
// Non-member function make() is unaffected.
// An overload will likely be needed for member functions.
template<typename Init>
auto make(Init func) { return InitFunc<Init>(func); }
Despite the awkwardness inside our derived specialisation, any code that relies on InitFunc shouldn't (to my knowledge) see any changes to its API; the previous example will work just fine if we swap to this new InitFunc, and be none the wiser after recompilation.
Note that it will change the ABI, though, and thus any code compiled for the simpler InitFunc will need to be recompiled for this version.

Pass a member function as Compare operator for C++ standard library algorithm

In my code I have now something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
[&bar](Foo const &lhs, Foo const &rhs) {
return bar.myWeakLessOperator(lhs, rhs);
});
I wonder wether it exists a way to simplify it by passing directly the member function myWeakLessOperator (that is not static) instead of writing a lambda function just to make to call.
I would like to obtain something like
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
/* something that rely to */ bar.myWeakLessOperator);
Any idea if it possible and how to do it ?
A possible solution is to use a struct that satisfies Compare inside Foo:
class Foo
{
public:
struct WeakLessOperator
{
bool operator()(const Foo& a, const Foo& b)
{
// implementation - take care of meeting requirements of Compare
return true;
}
};
WeakLessOperator myWeakLessOperator;
};
Foo bar;
auto minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
bar.myWeakLessOperator);
So you want to have a function object that represents a member function bound to a particular receiver. Unfortunately, there's nothing I could find in the standard or Boost that does that.
What you can do is write your own fairly easily.
template <typename R, typename T>
struct member_function_binder {
T *receiver;
R T::*pmf;
template <typename... Args>
auto operator()(Args&&... args) {
return (receiver->*pmf)(std::forward<Args>(args)...);
}
};
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return member_function_binder<R, T>{&receiver, pmf};
}
Have a look at the live demo, I think this might be what you want.
Even more concise, you don't need to have a separate class member_function_binder if you return a lambda from bind_member_function like so:
template <typename R, typename T>
auto bind_member_function(R T::*pmf, T &receiver) {
return [pmf, &receiver](auto&&... args) {
return (receiver.*pmf)(std::forward<decltype(args)>(args)...);
};
}
Live demo
Solution to pass a unary member function like Foo::compareTo(const Foo &rhs), not what OP asked:
What you want is std::mem_fn; it's a wrapper that makes a member function pointer into a function object. You would use it like this:
auto min = std::min_element(
begin(mySet), end(mySet), std::mem_fn(&Foo::myWeakLessOperator));
you can use std::bind, or some other wrapper.
EXAMPLE:
using namespace std::placeholders;
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
std::bind(&Foo::myWeakLessOperator, bar, _1, _2));
OR
Foo bar;
std::unordered_set<Foo>::iterator minElement =
std::min_element(std::begin(mySet),
std::end(mySet),
gnr::memfun<MEMFUN(Foo::myWeakLessOperator)>(bar));
The closest to what you want is maybe
auto minElement =
std::min_element(
std::begin(mySet),
std::end(mySet),
mem_fun_functor(&Foo::myWeakLessOperator)
);
There is std::mem_fun (deprecated in c++11) and std::mem_fn both wrap a member function pointer, though both take a instance as parameter to invoke the member function. If you want a functor that wraps the object also, i think you need to write your own:
auto mem_fun_functor =
[&bar](decltype(&Foo::myWeakLessOperator) f){
return [f,&bar](const Foo& a,const Foo& b) {
return (bar.*f)(a,b);
};
};
However, given that none of the answers is really much shorter or leading to cleaner code, I would consider to just use your first version with the lambda (unless you maybe have many different member functions that you want to use as comparator).
What do you actually mean by "simplifying" ? You do need to specify the object you want to call the member function on, you need to specify how you want to forward the parameters. Thats basically all the lambda does.
Defering all this to a functor as for example above makes your code more complicated rather than simpler. In your first snippet anybody familiar with standard algorithms can look at that few lines of code and fully understand what is going on.
Eventually it is a matter of style, and what you consider as readable, but being able to declare stuff in the most narrowest scope is one big advantage of using lambdas.

Forward a function into a lambda-expression in c++11

For a Packaged_Task implementation in C++11
i want to achieve what i've expressed in C++14 Code below. In other words i want to forward into a lambda expression.
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = [f = std::forward<F>(f)]() mutable { return std::move(f); };
///...
I'm aware of workarounds for moving into a lambda (but unfortenately this workarounds need a default constructible Object, in my case the object is most often a lambda expression without default-constructor)
How about creating a wrapper struct which does a move during copy construction:(. (I know that's bad, makes me remember of auto_ptr)
template <typename F>
struct Wrapped {
using Ftype = typename std::remove_reference<F>::type;
Wrapped(Ftype&& f): f_(std::move(f)) {}
Wrapped(const Wrapped& o): f_(std::move(o.f_)) {}
mutable Ftype f_;
};
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
Wrapped<std::remove_reference<decltype(f)>::type> wrap(std::forward<F>(f));
auto f_holder = [wrap]() mutable { return std::move(wrap.f_); };
This is just a rough idea. Not compiled or tested.
NOTE: I have seen this technique before, do not remember whether it was on SO itself or on some blog.
First, let's boil down the question to its core: the function object is somewhat of a distraction. Essentially, you want to be able to create a lambda with a capture holding a move-only object. In C++11 that isn't directly supported which gave raise to the C++14 approach of allowing specification of how the capture is build.
For C++11 it is necessary to use a copy. Since the underlying type doesn't support copying, it become necessary to actually move the object instead of copying it. Doing so can be achieved by a suitable wrapper defining a copy constructor not really copying but rather moving. Here is an example showing that:
#include <utility>
struct foo {
foo(int) {}
foo(foo&&) = default;
foo(foo const&) = delete;
};
template <typename T>
class move_copy
{
T object;
public:
move_copy(T&& object): object(std::move(object)) {}
move_copy(move_copy& other): object(std::move(other.object)) {}
T extract() { return std::forward<T>(this->object); }
};
template <typename T>
void package(T&& object)
{
move_copy<T> mc(std::forward<T>(object));
foo g = [mc]() mutable { return mc.extract(); }();
}
int main()
{
foo f(0);
package(std::move(f));
}
The move_copy<T> wrapper actually just captures the argument the way it is passed: if an lvalue is being passed in, an lvalue is captured. To properly get hold of the contained object, the extract() member std::forward<T>()s the object: the function can be called only once safely as an object is potentially moved from there.
Breaking copy semantics by making it a move is a bad idea. If it was the only option, go for it, but it is not.
Instead, we can pass the moved value in as an argument to the lambda, and move it into the wrapping code.
curry_apply takes some value and a function object, and returns that function object with the value bound to the first argument.
template<class T, class F>
struct curry_apply_t {
T t;
F f;
template<class...Args>
auto operator()(Args&&...args)
-> typename std::result_of_t<F&(T&, Args...)>::type
{
return f(t, std::forward<Args>(args)...);
}
};
template<class T, class F>
curry_apply_t<typename std::decay<T>::type, typename std::decay<F>::type>
curry_apply( T&& t, F&& f ) {
return {std::forward<T>(t), std::forward<F>(f)};
}
Use:
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = curry_apply(
std::move(_future),
[](Future<R>& f) mutable { return std::move(f); };
);
basically we store the moved-in data outside of the lambda in a manually written function object. We then pass it in as an lvalue argument at the front of the lambda's argument list.
Here is a more complex version of the same solution.

Overload function template based on parameter function argument type

I'm a class that looks like this:
template<typename A>
struct List {
...
template<typename Fn, typename B = typename std::result_of<Fn(A)>::type>
List<B> map(Fn f) const
{ ... }
};
I'm trying to overload map and allow it to accept a getter of type A as argument, so that we can do foos.map(&Foo::bar), where bar is a getter of class Foo. The following function works:
template<typename Fn, typename B = typename std::result_of<Fn(A*)>::type>
List<B> mapGet(Fn getter) const
{ ... }
But if I try to use the same name map, the compiler complains it's ambiguous. My question is, when Fn is a getter wouldn't the former std::result_of fail, effectively disabling one of the overloaded maps? Also, is there any way to make overloading possible?
My question is, when Fn is a getter wouldn't the former std::result_of fail, effectively disabling one of the overloaded maps?
I'm guessing by "getter" what you really mean is pointer to member function? In which case, std::result_of works just fine with those. Let's say we have some type Foo:
struct Foo {
Foo(int i) : i(i) { }
int bar() const { return i; }
int i;
};
You can use pointers to members as you'd expect:
using T = std::result_of_t<decltype(&Foo::bar)(Foo )>;
static_assert(std::is_same<T, int>{}, "!");
The only difference is how you actually call f. For C++17, there's std::invoke() which will work with all the invokable types, otherwise you could just directly use std::bind() or write your own wrapper which does the same thing.
As an example and ignoring copying, forwarding, and reserving, we could write map like:
template <class A, class F, class B = std::result_of_t<F(A)>>
std::vector<B> map(std::vector<A> xs, F f)
{
auto binder = std::bind(f, std::placeholders::_1);
std::vector<B> r;
for (auto& x : xs) {
r.push_back(binder(x));
}
return r;
}
That's works just as well for actual function objects:
std::vector<int> vs{1, 2, 3, 4, 5};
std::vector<double> ds = map(vs, [](int i){return i * 2.0; });
As it does for our Foo with a pointer to member:
std::vector<Foo> foos{1, 2, 3, 4, 5};
std::vector<int> is = map(foos, &Foo::bar);

Cast function type to differ if types of arguments are convertable

I am writing a wrapper class for callable types (pointer to function, functors, etc). I want to implement something like std::function.
I define constructor from pointer to function:
template <typename Ret, typename... Args>
class function<Ret(Args...)>
{
public:
function(Ret (func)(Args...))
{
m_fn_ptr = func;
}
}
Now, let's assume that i want to use my class like this:
int int_function(int n)
{
return n;
}
function<int(short)> wrapper(&int_function); // compile error
Despite that short are implicit convertable to int compiler cannot deduce template parameters and call appropriate constructor.
Then i tried this:
template <typename FRet, typename... FArgs>
function(FRet (func)(FArgs...))
{
m_fn_ptr = static_cast<Ret (*f)(Args...)>(func);
}
But I got invalid static cast.
How can I fix that ?
The super_func is a function object with no state that can convert to any compatible call signature.
template<class T>using type=T;
template<class Sig, Sig* func>
struct super_func;
template<class R, class...Args, R(*func)(Args...)>
struct super_func<R(Args...), func> {
using Sig = R(Args...);
using pSig = Sig*;
template<class R2, class...Args2, std::enable_if_t<
std::is_convertible<
std::result_of_t<pSig(Args2...)>,
R2
>{}
&& !std::is_same<R2, void>{},
bool
> =true>
constexpr operator type<R2(Args2...)>*() const {
return [](Args2...args)->R2{
return func(std::forward<Args2>(args)...);
};
}
template<class...Args2, std::enable_if_t<
std::is_same<
std::result_of_t<pSig(Args2...)>,
R
>{},
bool
> =true>
constexpr operator type<void(Args2...)>*() const {
return [](Args2...args)->void{
func(std::forward<Args2>(args)...);
};
}
constexpr operator pSig() const {
return func;
}
constexpr R operator()(Args...args)const{
return func(std::forward<Args>(args)...);
}
};
live example. A super_func is stateless. To use it on a function foo, do:
super_func< decltype(foo), &foo > super_foo;
and you get a callable stateless empty object which behaves a lot like foo does, except you can assign it to a pointer to any compatible function pointer and it generates it "on the fly" at compile time.
A super_foo can be fed to your function object.
Doing this on the fly doesn't work without the exterior help, as we need the foo to be a truly static bit of information. By the time it becomes a variable, it is too late to do this statelessly, so we cannot use the lambda trick (without an extra pvoid) to generate a function pointer for the exact signature we want.
You could do a macro:
#define SUPER(X) super_func< decltype(X), &X >{}
and then create your function object with function<double()> f(SUPER(foo));
Another approach is to store an extra pointer's worth of state, and create "the fastest possible delegate" style type erasure. (that term can be googled for one of many implementations, each faster than the last).
How can I fix that ?
Use the correct types when creating wrapper.
Instead of using
function<int(short)> wrapper(&int_function);
use
function<int(int)> wrapper(&int_function);
Remember that class templates instantiated with int and short are very different types and are not convertible to each other.
template <typename T> struct Foo {};
Foo<int> a;
Foo<short> b = a; // Not OK.
Foo<short> c;
Foo<int> d = c; // Not OK.
Your function constructor expects a pointer to a function that takes a short, not an int. The fix is to provide it such a function. The easiest way to do that is to use a lambda with an empty capture-list, that is implicitly convertible to a function pointer:
function<int(short)> wrapper( [](short s) { return int_function(s); } );