1

What I am trying to achieve is to make a functor that can take different functors as arguments.

Edit: the reason for my problem, the "most vexing parse", and the solution are well-described: see this question and answer, the whole tag, and even the wikipedia page. Still, I was not able to identify the problem before asking, and will leave this question as it might help others.

What I did:

In a header file functor.hpp:

#ifndef FUNCTOR_HPP
#define FUNCTOR_HPP

#include <functional>

template <typename T, typename BinOp = typename std::plus<T>>
struct doer {
    BinOp op;
    doer(BinOp o = std::plus<T>()) : op(o) {}
    T operator()(const T& a, const T& b) const
    { return op(a, b); }
};

#endif // FUNCTOR_HPP

With this header, I can write a program functor.cpp like this:

#include <iostream>
#include "functor.hpp"

int main()
{
    doer<int> f;
    std::cout << f(3, 7) << std::endl;
}

and I can compile and run it to get, as expected:

$ make functor
g++ -std=c++14 -pedantic -Wall    functor.cpp   -o functor
$ ./functor
10
$ 

I am struggling to find a way to instantiate my doer with a different operator (not std::plus<T>).

doer<int, std::multiplies<int>> f2(std::multiplies<int>());

This compiles without a problem, but I have not been able to figure out a way to call f2(3, 7), to get the product 21. For example, if I add another line to the program:

int r = f2(3, 7);

and try to compile, I get:

$ make functor
g++ -std=c++14 -pedantic -Wall    functor.cpp   -o functor
functor.cpp: In function ‘int main()’:
functor.cpp:10:20: error: invalid conversion from ‘int’ to ‘std::multiplies<int> (*)()’ [-fpermissive]
     int r = f2(3, 7);
                    ^
functor.cpp:10:20: error: too many arguments to function ‘doer<int, std::multiplies<int> > f2(std::multiplies<int> (*)())’
functor.cpp:9:37: note: declared here
     doer<int, std::multiplies<int>> f2(std::multiplies<int>());
                                     ^
functor.cpp:10:20: error: cannot convert ‘doer<int, std::multiplies<int> >’ to ‘int’ in initialization
     int r = f2(3, 7);
                    ^

What is going on? Seems almost like f2(3, 7) somehow is not calling the overloaded operator()...

Community
  • 1
  • 1
  • 1
    Sometimes it's worth compiling the code with clang as it provides better error messages. In this case, clang shows a warning: `parentheses were disambiguated as a function declaration [-Wvexing-parse]`. This explains the other compilaton errors. – Robin Krahl Aug 04 '15 at 13:27
  • 2
    The compiler thinks `f` is a function declaration. If you've access to C++11 use the uniform initialization syntax that was devised to handle such situations `doer> f{std::multiplies()};`. – legends2k Aug 04 '15 at 13:28
  • @legends2k Thank you for that, looks most convincing although there are at least two other way to write it, apparently. Not sure if this should be considered a "duplicate" since the title of the other question was not too useful in my case.... –  Aug 04 '15 at 13:31
  • 1
    Well, you can edit that question's title if it isn't appropriate. However, most vexing parse turns up in different places, in different contexts, so having a generic name would also not lead a lost one to it due to the _you don't know what you don't know_ issue :) – legends2k Aug 04 '15 at 13:33
  • @legends2k No, I guess I cannot edit the linked question, it is asked in a somewhat different context. I will leave it as it is, trying to reopen questions is a lost cause anyway. –  Aug 04 '15 at 13:37

1 Answers1

1

Most vexing parse. Try this:

doer<int, std::multiplies<int>> f2((std::multiplies<int>()));

or this:

doer<int, std::multiplies<int>> f2 = std::multiplies<int>();

or this:

doer<int, std::multiplies<int>> f2{std::multiplies<int>()};
yizzlez
  • 8,757
  • 4
  • 29
  • 44