-1

To explain my project, I'm trying to have a container the schedule objects derivated from a base class. The point is to launch a unspecified number of objects with a specific function and to run them into a certain order. To do that I need to get this specific function from the object.

So... I'm having trouble manipulating function pointers and polymorphism. I want to return a function pointer of my Class from class method.

I have this following base class:

#ifndef PLUGIN_POLYGON_BASE_H_
#define PLUGIN_POLYGON_BASE_H_

#include <iostream>
#include <functional>

typedef std::function<int(void*,void*)> return_function;


namespace polygon_base
{
  class RegularPolygon
  {
    public:
      virtual int area(void* in, void* out) = 0;
      virtual return_function getFunction(void) = 0;
      virtual ~RegularPolygon(){}


    protected:
      RegularPolygon(){}
  };  
};
#endif

I have this derivated class:

#include "polygon_base.h"
#include <cmath>

namespace polygon_plugin
{
  class Triangle : public polygon_base::RegularPolygon
  {
    public:
      Triangle(){}

      int area(void* in, void* out)
      {
        double* in_temp = (double*)in;
        double* out_temp = (double *)out;
        *out_temp = 0.5 *  *in_temp * getHeight(*in_temp);
        return 0;
      }

      return_function getFunction()
      {
        return std::bind(&Triangle::area, this);
      }

    private:
      double getHeight(double side_length_)
      {
        return sqrt((side_length_ * side_length_) - ((side_length_ / 2) * (side_length_ / 2)));
      }
    };

As you can see I'm trying to return the function area. I tried to do it without the std::function and the std::bind but couldn't manage to return the function pointer.

Right now I have this compilator error using g++ with c++ 11 standard.

/usr/include/c++/5/functional: In instantiation of ‘struct std::_Bind_check_arity<int (polygon_plugin::Triangle::*)(void*, void*), polygon_plugin::Triangle*>’:
/usr/include/c++/5/functional:1439:12:   required from ‘struct std::_Bind_helper<false, int (polygon_plugin::Triangle::*)(void*, void*), polygon_plugin::Triangle*>’
/usr/include/c++/5/functional:1462:5:   required by substitution of ‘template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...) [with _Func = int (polygon_plugin::Triangle::*)(void*, void*); _BoundArgs = {polygon_plugin::Triangle*}]’
polygon_plugin.h:27:47:   required from here
/usr/include/c++/5/functional:1426:7: error: static assertion failed: Wrong number of arguments for pointer-to-member
       static_assert(_Varargs::value
       ^
polygon_plugin.h: In member function ‘virtual return_function polygon_plugin::Triangle::getFunction()’:
polygon_plugin.h:27:25: error: could not convert ‘std::bind(_Func&&, _BoundArgs&& ...) [with _Func = int (polygon_plugin::Triangle::*)(void*, void*); _BoundArgs = {polygon_plugin::Triangle*}; typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type = std::_Bind<std::_Mem_fn<int (polygon_plugin::Triangle::*)(void*, void*)>(polygon_plugin::Triangle*)>](((polygon_plugin::Triangle*)this))’ from ‘std::_Bind_helper<false, int (polygon_plugin::Triangle::*)(void*, void*), polygon_plugin::Triangle*>::type {aka std::_Bind<std::_Mem_fn<int (polygon_plugin::Triangle::*)(void*, void*)>(polygon_plugin::Triangle*)>}’ to ‘return_function {aka std::function<int(void*, void*)>}’
         return std::bind(&Triangle::area, this);

It seems that bind doesn't have the right number of argument and I can't figure why and I don't understand the second error.

Can anyone help me with my problem ?

Thank you

2 Answers2

1

I think you need placeholders for the future arguments (i.e. the arguments of return_function)

using namespace std::placeholders;  // for _1, _2, _3...

std::bind(&Triangle::area, this, _1, _2);
john
  • 85,011
  • 4
  • 57
  • 81
  • Oh thx ! I tried std::bind(&Triangle::area, this, std::placeholders::_2); thinking that it means area had two arguments... didn't know I had to use std::bind(&Triangle::area, this, std::placeholders::_1, std::placeholders::_2); – Matthieu Amy Aug 22 '18 at 09:02
  • @MatthieuAmy it's more flexible to have a placeholder for each argument. For instance if your `in` and `out` arguments were swapped in `return_function` you would write `std::bind(&Triangle::area, this, _2, _1);` – john Aug 22 '18 at 09:08
0

you can use lambda expressions instead of bind

by replacing

std::bind(&Triangle::area, this);

by

[this](void* in, void *out){return area(in, out);};
john
  • 85,011
  • 4
  • 57
  • 81
Tyker
  • 2,971
  • 9
  • 21