2

I'm working on generic class that will be used to run functions of different prototype for performance testing of algorithms.

I stuck because std::function can't execute what it was bound with, here is sample code, with comment where the error happens:

#include <utility>
#include <functional>

template<typename ReturnType>
class Performance
{
public:
    template<typename... Args>
    using Algorithm = std::function<ReturnType(Args...)>;

    template<typename... Params>
    void run(const Algorithm<Params...>& ref, const Algorithm<Params...>& target)
    {
        // ERROR: term does not evaluate as taking 0 args
        ref();
        target();
    }
};

void bar1(int, int)
{
    // algorithm 1
}

void bar2(int, int)
{
    // algorithm 2
}

int main()
{
    using test = Performance<void>;
    using Algorithm = test::Algorithm<int, int>;

    int x = 0;
    int y = 1;

    Algorithm ref = std::bind(bar1, std::ref(x), std::ref(y));
    Algorithm target = std::bind(bar2, std::ref(x), std::ref(y));

    test foobar;

    foobar.run(ref, target);
}
metablaster
  • 1,958
  • 12
  • 26

1 Answers1

4

The problem is, the std::function type, i.e. Algorithm is declared to take two parameters (with type int); when calling on them two arguments are required.

After std::bind applied, the returned functors take no parameters; arguments (std::ref(x) and std::ref(y)) have been bound. Algorithm should be declared as

using Algorithm = test::Algorithm<>;

LIVE

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
  • 3
    @metablaster It might be confusing because you can set the functor returned from `std::bind` which takes nothing to `std::function` which is declared to take two `int`s. `std::function` takes type-erase trait. BTW: If you try to pass two `int`s in your original code, you'll find it could compile but the passed `int`s are not used at all. The bound arguments are used. [LIVE](https://wandbox.org/permlink/Z249vHyDDd4BcG3M) – songyuanyao May 23 '20 at 05:55