Mars
Mars

Reputation: 4995

Passing a function as an argument to another function

Why can a function like this

typedef std::vector<someclass> infocontainer;

double function2(const infocontainer&);

void function1(std::ostream&, const std::string&, double function2(const infocontainer&), const infocontainer, const infocontainer);

when called in main runs fine

function1(std::cout, "astring", function2, did, didnt);

But when function2 has a second argument it produces an error.

double function2(const infocontainer&, std::string&);

void function1(std::ostream&, const std::string&, double function2(const infocontainer&, const std::string&), const infocontainer, const infocontainer);

main

function1(std::cout, "astring", function2, did, didnt);

candidate function not viable: no known conversion from 'double (const infocontainer &, const
  std::string &)' to 'double (*)(const infocontainer &, std::string &)' for 3rd argument

Upvotes: 0

Views: 349

Answers (3)

Thomas Matthews
Thomas Matthews

Reputation: 57678

typedef is your friend with function pointers.
The typedef will reduce a lot of problems especially when specifying parameters for a function.

Example:

typedef double (*Pointer_To_One_Argument_Function)(const infocontainer&);  
typedef double (*Pointer_To_Two_Argument_Function)(const infocontainer&, std::string&);  

void function1A(std::ostream&, const std::string&, Pointer_To_One_Argument_Function, const infocontainer, const infocontainer);  
void function1B(std::ostream&, const std::string&, Pointer_To_Two_Argument_Function, const infocontainer, const infocontainer);  

In the above example, the typedef can make the declarations more readable.
Also, changing the type of the parameter is easier should you choose to change the number or types of the parameters for the function pointer.

As for your question, examine the syntax of the function pointer in your two parameter function pointer example.

Alternative: Function Objects (functors)

Rather than using the complex or complicated syntax for a function pointer, the C++ language offers another alternative: Function objects.
A function object is a class or struct that has an overloaded operator().
Example:

struct Function_Object_One_Parameter
{
   virtual double operator()(const infocontainer&) = 0;
};

struct Function_Object_Two_Parameter
{
   virtual double operator()(const infocontainer&, std::string&) = 0;
};

void function1C(std::ostream&, const std::string&, Function_Object_One_Parameter& f1, const infocontainer ic, const infocontainer)
{
  // ...
  f1(ic);
  // ...
}

void function1D(std::ostream&, const std::string& s, Function_Object_Two_Parameter& f2, const infocontainer ic, const infocontainer)
{
  // ...
  f2(ic, s);
  // ...
}

To use this pattern, declare functions derived from Function_Object_One_Parameter or Function_Object_Two_Parameter:

struct Happy_Function_One
: public Function_Object_One_Parameter
{
  double  operator()(const infocontainer&)
  {
    std::cout << "Happy" << std::endl;
    return 3.14159267;
  }
}

Upvotes: 1

Dialecticus
Dialecticus

Reputation: 16761

"no known conversion from"

double (const infocontainer &, const  std::string &)

"to"

double (*)(const infocontainer &, std::string &)

The difference is in const to second argument. You may think that the function is defined as double function2(const infocontainer&, const std::string&); but your compiler disagrees.

Upvotes: 3

youdontneedtothankme
youdontneedtothankme

Reputation: 672

Because the code you have posted is not the same that the code you are trying to compile.

The following line

void function1(std::ostream&, const std::string&, double function2(const infocontainer&, const std::string&), const infocontainer, const infocontainer);

is missing a const before std::string & in the third parameter in the code you are trying to compile.

Upvotes: 1

Related Questions