Generate functor with shared_from_this - c++

I'd like to create a functor from a class A that inherits from enable_shared_from_this, that is for a class like this:
class A: public std::enable_shared_from_this<A> {
...
}
I want to have a member function that looks something like this (incorrect code):
template <typename Args...>
std::function<void(Args ...)> functor_from_this(void (A::*method)(Args...)) {
return std::bind(method, shared_from_this());
}
The code above generates several errors, starting with warning C4180: qualifier applied to function type has no meaning; ignored, which makes me suspect I'm going about this the wrong way. How do I go about achieving something like this?
Extra credits for (a) binding the Args... to the functor as well so I get a function whose signature is void fn(), and (b) doing all this in a general-purpose class that inherits from enable_shared_from_this<T>.

Well, for C++14 the solution is easy enough to write. Just forgo std::bind and return a lambda instead:
#include <memory>
#include <iostream>
#include <functional>
struct A: std::enable_shared_from_this<A> {
template <typename... Args>
std::function<void(Args...)> functor_from_this(void (A::*method)(Args...)) {
return [=, obj = shared_from_this()](Args... args) {
((*obj).*method)(args...);
};
}
void foo(int) { std::cout << "foo" << '\n'; }
void bar() { std::cout << "bar" << '\n'; }
};
int main()
{
auto a = std::make_shared<A>();
auto f = a->functor_from_this(&A::foo);
auto b = a->functor_from_this(&A::bar);
f(1);
b();
}
For C++11 as Jarod42 pointed out in a comment, use a much simpler intermediate variable:
#include <memory>
#include <iostream>
#include <functional>
struct A: std::enable_shared_from_this<A> {
template <typename... Args>
std::function<void(Args...)> functor_from_this(void (A::*method)(Args...)) {
auto obj = shared_from_this();
return [=](Args... args) {
((*obj).*method)(args...);
};
}
void foo(int) { std::cout << "foo" << '\n'; }
void bar() { std::cout << "bar" << '\n'; }
};
int main()
{
auto a = std::make_shared<A>();
auto f = a->functor_from_this(&A::foo);
auto b = a->functor_from_this(&A::bar);
f(1);
b();
}

For extra credit (B), here is the solution I found, based on the answer by StoryTeller & Jarod:
#include <memory>
#include <iostream>
#include <functional>
template <class T>
class enable_functor_from_this: public std::enable_shared_from_this<T> {
public:
template <typename... Args>
decltype(auto) functor_from_this(void (T::*method)(Args...)) {
auto obj = this->shared_from_this();
return [=](Args... args) {
((*obj).*method)(args...);
};
}
};
struct A: enable_functor_from_this<A> {
void foo(int) { std::cout << "foo" << '\n'; }
void bar() { std::cout << "bar" << '\n'; }
};
int main()
{
auto a = std::make_shared<A>();
auto f = a->functor_from_this(&A::foo);
auto b = a->functor_from_this(&A::bar);
f(1);
b();
}

Related

Template conversion operator in template class - to function pointer

I'm trying to make my class be convertible to a function pointer, for a slew of reasons unrelated to this post.
When I try to do this with a non-template class, it works fine. Below, Bar bar; bar(1) correctly compiles, and segfaults as-expected. But Foo<int>; foo(1) doesn't compile at all.
I've tried multiple compilers, and I get: mismatched types 'Args' and 'int'
Any ideas? Live demo: https://wandbox.org/permlink/alSGBssfSd4pHgdl
#include <iostream>
#include <tuple>
using namespace std;
template<typename... Args>
using Test = void(*)(Args...);
template<typename T>
struct Foo {
template<typename... Args>
operator Test<Args...>() {
return Test<Args...>{};
}
};
struct Bar {
template<typename... Args>
operator Test<Args...>() {
return Test<Args...>{};
}
};
int main()
{
Foo<int> foo;
// foo(1);
Bar bar;
bar(1);
return 0;
}
Tried this awful syntax, too:
template<typename... Args>
(*operator void() const)(Args...) {
return {};
}
You can try this:
#include <iostream>
#include <tuple>
using namespace std;
template<typename... Args>
using Test = void(*)(Args...);
template<typename T>
struct Foo {
template<typename... Args>
operator Test<Args...>()
{
std::cout << __FUNCTION__ << std::endl;
return Test<Args...>{};
}
};
struct Bar {
template<typename... Args>
operator Test<Args...>()
{
std::cout << __FUNCTION__ << std::endl;
return Test<Args...>{};
}
};
int main()
{
Foo<int> foo;
auto x = static_cast<Test<int, double>>(foo);
Bar bar;
auto y = static_cast<Test<char, float>>(bar);
return 0;
}
When using Visual C++ 2019, I get the following run-time output:
Foo<int>::operator void (__cdecl *)(int,double)
Bar::operator void (__cdecl *)(char,float)
The use of the static_cast is to force the usage of the overloaded operator member functions.
Alternatively, you can also try:
#include <iostream>
#include <tuple>
#include <type_traits>
using namespace std;
template<typename... Args>
using Test = void(*)(Args...);
template<typename T>
struct Foo {
template<typename... Args>
Test<Args...> operator()(int x)
{
return Test<Args...>{};
}
};
struct Bar {
template<typename... Args>
Test<Args...> operator()(int x)
{
return Test<Args...>{};
}
};
int main()
{
Foo<int> foo;
auto w = foo.template operator()<int, double>(1);
std::cout << "w: " << typeid(w).name() << std::endl;
auto x = foo(2);
std::cout << "x: " << typeid(x).name() << std::endl;
Bar bar;
auto y = bar.template operator()<char, float>(3);
std::cout << "y: " << typeid(y).name() << std::endl;
auto z = bar(4);
std::cout << "z: " << typeid(z).name() << std::endl;
return 0;
}
When using Visual C++ 2019, I get the following run-time output:
w: void (__cdecl*)(int,double)
x: void (__cdecl*)(void)
y: void (__cdecl*)(char,float)
z: void (__cdecl*)(void)
In this way, the object is now callable and returns a function pointer.

type trait for function pointer?

I need to conditionally use either std::abs or std::fabs inside template class, here is relevant code in simplified version:
template <typename T>
class C
{
public:
using type = std::conditional_t<std::is_integral_v<T>, std::uint64_t, long double>;
using check = std::is_integral<type>;
// ERROR: mismatch in format parameter list
constexpr auto ptr_abs = check::value ? &std::abs<check::value_type> : &std::fabs;
// use pointer
void use_ptr()
{
auto x = (*ptr_abs)(-3);
}
};
None of the attempts worked for me, I'm clueless.
int main()
{
C<int> a;
a.f();
C<float> b;
b.f();
}
Do you really need to work with function pointers? Wouldn't be better to exploit C++ type-safe mechanisms? Such as follows:
template <typename T>
class C
{
public:
using type = std::conditional_t<std::is_integral_v<T>, std::uint64_t, long double>;
static const bool check = std::is_integral_v<type>;
std::function<type(type)> abs = [](auto arg)
{
if constexpr (check) return std::abs(static_cast<long long>(arg));
else return std::fabs(arg);
};
void use()
{
auto x = abs(-3);
}
};
This works for me well. Just note that there is no std::abs for unsigned integers, therefore, to avoid ambiguity, I had to choose a particular overload by casting (to long long in this example; I don't know what is Result).
Before C++17, where there is no if constexpr, you can achieve the same just with some more typing by using template specializations.
Resolve the function overload with the type of the pointer:
#include <cmath>
#include <type_traits>
#include <cstdlib>
#include <iostream>
template <typename T>
class C {
public:
static constexpr T (*ptr_abs)(T) = &std::abs;
void f() {
std::cout << typeid(ptr_abs).name() << "\n";
auto x = (*ptr_abs)(-3);
}
};
int main()
{
C<int> a;
a.f(); // PFiiE
C<float> b;
b.f(); // PFffE
C<double> c;
c.f(); // PFddE
}
Maybe I've misunderstood your problem, but it seems to me that you could separately define your version of abs that behaves as you want and then use it inside other classes
#include <cmath>
#include <cstdint>
#include <complex>
#include <iostream>
#include <limits>
#include <type_traits>
#include <typeinfo>
namespace my {
template <class T>
auto abs_(T x)
{
if constexpr ( std::is_unsigned_v<T> ) {
return static_cast<uintmax_t>(x);
}
else if constexpr ( std::is_integral_v<T> ) {
return static_cast<uintmax_t>(std::abs(static_cast<intmax_t>(x)));
}
else {
return std::fabs(static_cast<long double>(x));
}
}
template <class T>
auto abs_(std::complex<T> const& x)
{
return std::abs(static_cast<std::complex<long double>>(x));
}
}
template <typename T>
class C
{
public:
void use(T x)
{
std::cout << typeid(T).name() << ' ' << x;
auto a = my::abs_(x);
std::cout << ' ' << typeid(a).name() << ' ' << a << '\n';
}
};
int main()
{
C<int> a;
a.use(-42);
C<float> b;
b.use(-0.1);
C<long long> c;
c.use(std::numeric_limits<long long>::min());
C<size_t> d;
d.use(-1);
C<std::complex<double>> e;
e.use({-1, 1});
}
Testable here.

Unexpected nullptr in expansion of variadic template constructor

Difficult to explain, here a short stand-alone example of what I mean:
#include <functional>
#include <iostream>
typedef std::function<void(void)> f_t;
struct A { A(f_t f) { f(); } };
struct B { B(f_t f) { f(); } };
struct C { C(f_t f) { f(); } };
template<typename ... TT>
struct T : TT...
{
T( ) : TT([this](void) { std::cout << this << std::endl; })...
{
}
};
int main(void)
{
T<A, B, C> t;
return 0;
}
Output:
0x7ffe84574e6f
0
0
My class template T inherits from its template parameter pack TT. Each type of TT expects a functor as constructor argument. When I try to pass a functor that captures this during the constructor calls, all but the first constructor call of the expansion actually receive a functor that captured nullptr as this. If I delegate the functor creation to a member function, it works as intended:
template<typename ... TT>
struct T : TT...
{
T( ) : TT(genF())...
{
}
f_t genF( ) { return [this](void) { std::cout << this << std::endl; }; }
};
Output:
0x7ffefca4e61f
0x7ffefca4e61f
0x7ffefca4e61f
(Compiler used is GCC 4.6.3)
What causes this behavior? Is it a compiler bug? Or am I missing something?

Specialize member pointer template argument resolution

Having guard class on C++11 that is responsible to invoke some member function on scope exit:
template <class T, void (T::*op)()>
struct Guard
{
Guard(T*g):
_g(g){}
~Guard()
{
(_g->*op)();
}
T*_g;
};
Usage is very simple:
typedef Guard<Foo, &Foo::bar> FooGuard;
...
FooGuard g(&foo);
My question originated from existing shared_ptr<Foo>. How to create specialization that keeps shared_ptr<T> instead of T*
What I've already tried:
template <class T, void (T::*op)()>
struct Guard<std::shared_ptr<T>, op>
{
Guard(std::shared_ptr<T>& g):
_g(g){}
~Guard()
{
((*_g).*op)();
}
std::shared_ptr<T> _g;
};
But during compilation on G<std::shared_ptr<Foo>, &Foo::bar> g2(foo); have foreseeable got:
error C2440: 'specialization' : cannot convert from 'overloaded-function' to 'void (__thiscall std::shared_ptr::* )(void)'
as #PiotrSkotnicki already pointed out, your specialization is not valid.
You could use something like the following, however the interface does not look that nice:
template <class T, class U, void (U::*op)()>
struct Guard
{
Guard(T*g):
_g(g){}
~Guard()
{
std::cout << "normal guard" << std::endl;
(_g->*op)();
}
T*_g;
};
template <class T, class U, void (U::*op)()>
struct Guard<std::shared_ptr<T>, U, op>
{
Guard(std::shared_ptr<T>& g):
_g(g){}
~Guard()
{
std::cout << "shared_ptr guard" << std::endl;
((*_g).*op)();
}
std::shared_ptr<T> _g;
};
Demo:
struct Foo
{
void bar()
{
std::cout << "Foo::bar()" << std::endl;
}
};
int main()
{
Foo foo;
{
typedef Guard<Foo, Foo, &Foo::bar> FooGuard;
FooGuard g(&foo);
}
std::shared_ptr<Foo> foo_ptr = std::make_shared<Foo>();
{
typedef Guard<std::shared_ptr<Foo>, Foo, &Foo::bar> FooGuard;
FooGuard g(foo_ptr);
}
return 0;
}
Output:
normal guard
Foo::bar()
shared_ptr guard
Foo::bar()
live example
I would suggest using lambda functions instead and capture by value:
#include <functional>
#include <memory>
struct Guard
{
typedef std::function<void()> func_type;
Guard( const func_type& f ): func(f) {}
~Guard() { if (func) func(); }
func_type func;
};
struct Foo
{
void bar() {}
};
int main()
{
auto foo_ptr = std::make_shared<Foo>();
Guard g([foo_ptr](){ foo_ptr->bar(); }); // note the capture by value
}
Note that you are free to capture by reference too, if you want to guard an instance allocated on the stack for example.
If you really want to stick to the ugly way, I would suggest using deleters:
#include <string>
#include <memory>
#include <cstdio>
template < class T, void (T::*op)() >
struct Guard
{
Guard( T *p ): ptr( p, [](T*){} ) {}
Guard( const std::shared_ptr<T>& p ): ptr(p) {}
~Guard() { if (ptr) ((*ptr).*op)(); }
std::shared_ptr<T> ptr;
};
struct Foo
{
Foo( const char* n ): name(n) {}
void bar() { printf("Hello from %s\n",name.c_str()); }
std::string name;
};
int main()
{
auto foo1 = Foo("Bob");
auto foo2 = std::make_shared<Foo>("Alice");
Guard<Foo,&Foo::bar> g1(&foo1), g2(foo2);
}

boost::function alike class

I would like to realize a class Function similar to boost::function, the class Function can use like this in main.cpp :
#include <iostream>
#include "Function.hpp"
int funct1(char c)
{
std::cout << c << std::endl;
return 0;
}
int main()
{
Function<int (char)> f = &funct1;
Function<int (char)> b = boost::bind(&funct1, _1);
f('f');
b('b');
return 0;
}
In my Function.hpp, I have
template <typename T>
class Function;
template <typename T, typename P1>
class Function<T(P1)>
{
typedef int (*ptr)(P1);
public:
Function(int (*n)(P1)) : _o(n)
{
}
int operator()(P1 const& p)
{
return _o(p);
}
Function<T(P1)>& operator=(int (*n)(P1))
{
_o = n;
return *this;
}
private:
ptr _o; // function pointer
};
Above code works fine for Function f = &funct1, but it can't work for Function b = boost::bind(&funct1, _1); I wonder to know how exactly boost::Function works and What can I do to for my Function support boost::bind