2

I'm trying to have a function pointer where, in some cases, it either is assigned a function takes in 2 arguments (a cv::Mat and a struct that contains parameters) or a different function that takes 3 arguments (the same 2 arguments and a list of coordinates). I figure that std::function and std::bind are what I'm supposed to be using here.

Mat process_F1(cv::Mat img, feature_params f);
Mat process_F1_coords(cv::Mat img, feature_params f, std::vector<std::pair<int, int> > feature_coords c);
Mat process_F2(cv::Mat img, feature_params f);
Mat process_F2_coords(cv::Mat img, feature_params f, std::vector<std::pair<int, int> > feature_coords );
// this is the function pointer that will hold them
std::function<cv::Mat()> feature_func_f;
//this is how I assign them:
void set_feature_func(int feature_method, bool use_coords)
{
    switch (feature_method){
    case 0:
            if( !use_coords )
                feature_func_f = std::bind(process_F1,std::placeholders::_2);
            else
                feature_func_f = std::bind(process_F1_coords,std::placeholders::_3);  
            break;
        case 1:
            if( !use_coords )
                feature_func_f = std::bind(process_F2,std::placeholders::_2);
            else
                feature_func_f = std::bind(process_F2_coords,std::placeholders::_3);   
            break;
}

I intend to call feature_func_f as:

cv::Mat m, n;
feature_params p;
set_feature_func(0,false);

n = feature_func_f(m,p);

// or if I have a coordinate list c
std::vector<std::pair<int, int> > c;

set_feature_func(0,true);
n = feature_func_f(m,p,c);

What am I doing wrong here? I get a bunch of errors that aren't really meaningful in the header for functional:

Error   4   error C2977: 'std::add_reference' : too many template arguments C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional   900 1   
Error   5   error C2955: 'std::add_reference' : use of class template requires template argument list   C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional   900 1   
Error   6   error C2198: 'cv::Mat (__cdecl *)(cv::Mat,feature_params)' : too few arguments for call C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional   1149    1   
Error   2   error C2146: syntax error : missing ',' before identifier 'type'    C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional   900 1   
Error   3   error C2065: 'type' : undeclared identifier C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional   900 1   
Error   1   error C2027: use of undefined type 'std::tuple_element<0x01,_Ftuple>'   C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\include\functional   900 1   
Hal T
  • 527
  • 7
  • 22
  • 3
    Remove things that do not impact your question, like `Matcher::` and have it compile & generate the error all by itself. Please post every error, or at least **first** set of errors (the errors that start at the top, and go down to the part where *your code* is mentioned) -- a random selection of errors isn't that useful. Wait a sec, do you think `_2` and `_3` are the number of placeholders? Have you ever used `std::placeholders` successfully? How do you intend to **invoke** `feature_func_f`? – Yakk - Adam Nevraumont Jul 13 '15 at 14:08
  • I cleaned up the question and clarified how I will call the function. – Hal T Jul 13 '15 at 14:20

2 Answers2

3

No, you cannot do, what you want. std::bind is just for binding arguments, that shouldn't be used in function call. You can either use 2 functions, one for 2 params and one for 3 params, or send coords to function set_feature_func.

Just simple example about usage of std::function and std::bind.

#include <functional>
#include <iostream>

int main()
{
   std::function<void(int)> function;
   auto l1 = [](int v) { std::cout << v << std::endl; };
   auto l2 = [](int v1, int v2) { std::cout << v1 << " " << v2 << std::endl; };
   function = l1;
   function(5);
   function = std::bind(l2, std::placeholders::_1, 10);
   function(5);
}

And your code should be like

std::function<cv::Mat(cv::Mat, feature_params)> feature_func_f;

// coords is vector<vector<...>>
void set_feature_func(int feature_method, coords)
{
   // switch
      if (coords.empty())
      {
         feature_func_f = process_f1;
      }
      else
      {
         feature_func_f = std::bind(process_f1, _1, _2, coords);
      }
}

Usage

std::vector<std::pair<int, int> > c;

set_feature_func(0,true,c);
n = feature_func_f(m,p);
ForEveR
  • 55,233
  • 2
  • 119
  • 133
0

As a general rule, the type of a variable determines what kind of operations you can operate on the variable with.

feature_func_f has one type. A previous function call cannot change its type.

std::function supports one argument signature.

Thus n = feature_func_f(m,p); and n = feature_func_f(m,p,c); cannot both be valid on a std::function.

There are ways around this, but in this kind of case there isn't much point. Have two feature_func_f, each with a different signature, and invoke the right one.

std::function<cv::Mat(cv::Mat img, feature_params f)> feature_func_f;
std::function<cv::Mat(cv::Mat img, feature_params f, std::vector<std::pair<int,int>>)> feature_func_vector_f;
Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524