1

Perhaps I am way out of left field with this question, but is it possible to define a member function via the constructor?

In my case, I am trying to write a class to perform robust model fitting (using RANSAC). I want this to be generalizable to different types of models. For example, I could use this to determine an estimate of a plane to a set of 3D points. Or, perhaps I could determine a transformation between two sets of points. In these two examples, there might need to be different error functions and different fitting functions. Instead of using a class, a static function call might look like

model = estimate(data, &fittingFunc, &errorFunc);

I'm wondering if I can have member instance for those modular functions?

Something like

class Estimator
{
    private:
        // estimation params

        double errorFunc(std::vector<dtype>, double threshold); // Leave this unimplemented
        double fittingFunc(std::vector<dtype>, Parameters p); // Leave this unimplemented

    public:
        Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double));

        dtype estimate(data); // Estimates model of type dtype. Gets implemented

};

Estimator::Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
{
    fittingFunc = fittingFunc;
    errorFunc = errorFunc;
}

I imagine I have bastardized the proper syntax in my example, but I hope the question is clear. Basically I am asking: Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?

Secondly, even if this is possible, is it considered bad form?

UPDATE: If it helps, here is MATLAB code for robust estimation that has this sort of generalizable structure I'm hoping to replicate in C++

marcman
  • 3,233
  • 4
  • 36
  • 71
  • the answer to your question is **yes**. and correct your code in `double);` and this semicolon is for what? – Shakiba Moshiri Feb 06 '17 at 20:41
  • @k-five: Typo, sorry. And yes, it's possible? Or yes, it's bad form? Or both? – marcman Feb 06 '17 at 20:43
  • The [***Pimpl idiom***](http://stackoverflow.com/questions/60570/why-should-the-pimpl-idiom-be-used) might be a better approach though. – πάντα ῥεῖ Feb 06 '17 at 20:44
  • 2
    it being bad form is absolutely dependent on what the function is for and how objects with this function are being defined. This kind of problem can also be solved by virtual functions and polymorphism – kmdreko Feb 06 '17 at 20:44
  • 1
    Prefer to use `typedef` to create synonyms for your function pointer syntaxes; they simplify the code. – Thomas Matthews Feb 06 '17 at 20:44
  • Also, prefer to pass `vector` by reference or constant reference. You don't want to put large structures on the *stack*. – Thomas Matthews Feb 06 '17 at 20:46
  • @vu1p3n0x: In this case, I want to write one header file that can be used for multiple purposes. So for a different project down the road, I can just provide difference fitting and error functions and include this file. I believe that using virtual functions and polymorphism would require extending the class any time I want to fit a different type of model, no? – marcman Feb 06 '17 at 20:47
  • you might want something like this: https://ideone.com/z7n4OQ – RyanP Feb 06 '17 at 20:48
  • You can't change the address of a member function as you show above, you either need to save a function pointer and use that, or have the member function forward to a function pointer, which can be provided in the constructor. – lcs Feb 06 '17 at 20:49

2 Answers2

5

Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?

No. Not as member functions. But you can certainly have public member function pointers:

class Estimator
{
public:
    double (*errorFunc)(std::vector<dtype>, double threshold);
    double (*fittingFunc)(std::vector<dtype>, Parameters p);

public:
    Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
    : errorFunc(errorFunc)
    , fittingFunc(fittingFunc)
    { }

    dtype estimate(data);    
};

For a nicer (or safer) interface, you can make the function pointers private and have a public member function which simply invokes them.


More generally, if you're okay with the overhead, you can have members of type std::function<double(std::vector<dtype>, double)> and std::function<double(std::vector<dtype>, Parameters)> and then you can use a wider variety of callables (function pointers, but also lambdas, bound member functions, etc.)

Barry
  • 286,269
  • 29
  • 621
  • 977
  • This seems to be what I had in mind, particularly with private pointers. I'll try it, and if it works accept this – marcman Feb 06 '17 at 20:51
  • Thank you. I was going nuts trying to find where in the standard it allowed [something like this](http://ideone.com/r4rr2j) and why I couldn't get it to work thanks to the emphatic Yeses in the comments. – user4581301 Feb 06 '17 at 20:55
  • @M.M I suggested that. – Barry Feb 06 '17 at 21:03
  • @Barry Sorry I have a question, `typedef` of a function pointer and create an object of that function pointer is not a **member function**. – Shakiba Moshiri Feb 06 '17 at 21:11
  • 1
    @k-five that's why the answer says "No" and then gives an alternative to achieve the same goal – M.M Feb 06 '17 at 21:12
  • 2
    @k-five that discussion is beyond the scope of comments, [see here](http://en.cppreference.com/w/cpp/utility/functional/function) – M.M Feb 06 '17 at 21:14
  • @M.M Sorry but I thought the answer is **yes**. Please tell me that `typedef Return( *Fo_t )( Argument )` inside a `struct` like this: `Fo_t func;` then this is a member data or a member function? – Shakiba Moshiri Feb 06 '17 at 21:19
  • @k-five if you think the answer is "yes" then post an answer, and people will comment and vote on it. In your code `func` is a member variable. – M.M Feb 06 '17 at 21:20
  • @M.M Unfortunately I am not sure and I ask you for that – Shakiba Moshiri Feb 06 '17 at 21:21
1

Yes you can provide the algorithm for your fitting and error function. You could do it using pointer to function. And there is a better solution, in the standard header you will find the template std::function which can be constructed with pointer to function but also with functors or lambda expressions.

Your class would be something like this:

 #include <functional>
 class Estimator
 {
 private:
    // estimation params
    using error_func_type =   std::function<double(std::vector<dtype>,double)>;
    using fitting_func_type = std::function<double(std::vector<dtype>,Parameters p)>;
    fitting_func_type fittingFunc;
    error_func_type errorFunc;


public:
    Estimator(fitting_funct_type fit, error_funct_type err)
      :fittingFunc(fit),errorFunc(err){}

    dtype estimate(data); // Estimates model of type dtype. Gets implemented

 };
Oliv
  • 17,610
  • 1
  • 29
  • 72