1

../1.63/boost/bind/bind.hpp:75:22: Type 'void (*)(const uint32_t &)' cannot be used prior to '::' because it has no members

My code looks something like:

template<typename T>
using RunStep = void (*)(const T& steps);

template<typename StepType, typename T>
class Stepper
{
public:
 virtual void StepUp() = 0;
protected:
  RunStep<StepType> runStepCallBack;
  T data;
}


class StepperIO : public Stepper<uint32_t, std::string>
{
 virtual void StepUp()
 {
    boost::bind(runStepCallBack,this, _1); //
 }
}

Is it even possible? Its just a psuedo-code

JamesWebbTelescopeAlien
  • 3,547
  • 2
  • 30
  • 51
  • Are you trying to bind a variable? `runStepCallBack` is not a function! – The Quantum Physicist Apr 13 '17 at 06:08
  • @TheQuantumPhysicist `runStepCallBack` is a member of type `RunStep` which is a function pointer, so you can use `bind` on it. – Holt Apr 13 '17 at 06:11
  • @NulledPointer Explain what you want to in the end - How are you gonna use the result of `boost::bind`? It's completely unclear what you want to do here... `runStepCallBack` is a pointer to a function that takes a `uint32_t` and you're trying to bind it with `this` which is of type `StepperIO*` + something. – Holt Apr 13 '17 at 06:23
  • @Holt I want runStepCallBack to be part of pure virtual class to for that to be a generic interface for all the deriving class. StepperIO::Execute() will then call this function with instance of StepperIO. – JamesWebbTelescopeAlien Apr 13 '17 at 16:37

1 Answers1

1

If the callback must also access the members of the actual stepper instance, then, no. Either

  1. you explicitly pass the this argument into the callback (public API's often use an "opaque" argument like void* user_data)
  2. or create a function object, e.g. using a lambda, boost::bind, std::bind or manually. Function objects can hold state. The standard library and boost have a type-erasing container for such callbacks: std::function<void(T)> (or boost::function<...>).

Demos:

Live On Coliru

#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <iostream>

template<typename T>
using RunStep = boost::function<void(const T& steps)>;

template<typename StepType, typename T>
class Stepper
{
    public:
        virtual void StepUp() = 0;
    protected:
        RunStep<StepType> runStepCallBack;
        T data;
};

class StepperIO : public Stepper<uint32_t, std::string>
{
  public:
    template <typename F>
    void setCallback(F f) { runStepCallBack = f; }
    virtual void StepUp() { runStepCallBack(1); }
};

struct Sample {
    void foo(int32_t i) const { std::cout << __FUNCTION__ << "(" << i << ")\n"; }
    void bar(int32_t i) const { std::cout << __FUNCTION__ << "(" << i << ")\n"; }
    void qux(int32_t i) const { std::cout << __FUNCTION__ << "(" << i << ")\n"; }
};

int main() {
    StepperIO io;

    Sample demo;
    io.setCallback(std::bind(&Sample::foo, demo, std::placeholders::_1));
    io.StepUp();

    io.setCallback(boost::bind(&Sample::bar, demo, _1));
    io.StepUp();

    io.setCallback([&demo](int32_t i) { demo.qux(i); });
    io.StepUp();
}

Prints

foo(1)
bar(1)
qux(1)

My feeling is that the type-erasure is exactly what you were looking for, see more enlightening answers:

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Added reference to type-erased polymorphism, because it "smells like" you are looking for that – sehe Apr 13 '17 at 07:23
  • @NulledPointer Sure! It means that the type 'void (*)(const uint32_t &)' cannot be used prior to '::' . In other words, that type (that you pass, it's `RunStep`) is being used before `::` (you can obviously just look at line 75 of boost/bind/bind.hpp, where you'll obviously find something like `::result_type` or similar in column 22. Just a guess. – sehe Apr 13 '17 at 22:03