1

I have the following functor which wraps another functor or lambda function and automatically sets an index parameter. An example will explain best. I can do the following:

auto f = stx::with_index([](int a, int index){ std::cout << a << " " << index << std::endl; });
f(5);
f(3);
f(9);

Output:

5 0
3 1
9 2

Here is the functor code:

template<class FUNC>
class IndexFunctor
{
public:
    typedef FUNC FUNC_T;

    explicit IndexFunctor(const FUNC_T& func) : func(func), index(0) {}

    template<class... ARGS>
    void operator ()(ARGS&&... args)
    {
        func(args..., index++);
    }

    const FUNC_T& GetFunctor() const
    {
        return func;
    }

    int GetIndex() const
    {
        return index;
    }

    void SetIndex(int index)
    {
        this->index = index;
    }

private:
    FUNC_T func;
    int index;
};

template<class FUNC>
IndexFunctor<FUNC> with_index(const FUNC& func)
{
    return IndexFunctor<FUNC>(func);
}

Now the problem is I want to use it with functions that may return a value. For example

auto f = stx::with_index([](int a, int index){ return a * index; });
int a = f(5);

But I cannot figure out how to modify my functor to get this to work. I would like the functor to be compatible with both functions that return a value and those that don't automatically.

Can anyone offer some suggestions? Thanks!

I am using VS2012 Microsoft Visual C++ Compiler Nov 2012 CTP

Neil Kirk
  • 21,327
  • 9
  • 53
  • 91

1 Answers1

6

You have to change what your operator() returns.

If you're using C++11 you can do it with trailing return types.

template<typename... Args> 
auto operator ()(Args&&... args) 
-> decltype(func(std::forward<Args>(args)..., index++)) //get return type
{
    return func(std::forward<Args>(args)..., index++);
}
Puppy
  • 144,682
  • 38
  • 256
  • 465
Tony The Lion
  • 61,704
  • 67
  • 242
  • 415
  • ha you fixed it before I did – sehe Aug 04 '13 at 23:29
  • error C2893: Failed to specialize function template 'unknown-type stx::IndexFunctor>::operator ()(Args &&...)' 1> With the following template arguments: 1> 'int' – Neil Kirk Aug 04 '13 at 23:32
  • I am using VS2012 with Microsoft Visual C++ Compiler Nov 2012 CTP – Neil Kirk Aug 04 '13 at 23:33
  • @Neil: The CTP has a billion variadic template bugs in it. If the code doesn't work, I'd first try with some other compilers before assuming the code is wrong. – Puppy Aug 04 '13 at 23:34
  • Could you explain the use of std::forward and why index++ twice, in your answer please? – Neil Kirk Aug 04 '13 at 23:35
  • `std::forward` forwards the value category of the argument, so that if you passed an lvalue it will pass on an lvalue, if you passed an rvalue, it passed on rvalue. `decltype` figures out the type of the expression passed inside it, so that can know the return type of your functor. – Tony The Lion Aug 04 '13 at 23:38
  • Also have a look at this: http://stackoverflow.com/questions/3582001/advantages-of-using-forward – Tony The Lion Aug 04 '13 at 23:38
  • Also this: http://stackoverflow.com/questions/16762263/what-does-after-a-function-prototype-mean – Tony The Lion Aug 04 '13 at 23:39
  • Hi @NeilKirk. You need to declare Func and index before your function. http://ideone.com/23Ntoz – Tony The Lion Aug 04 '13 at 23:48
  • Ok thanks! That works on ideone but still does not work on VS2012, so I just assume it's a compiler bug. If you could come up with an alternative way that might work in my compiler I would be really happy :) – Neil Kirk Aug 04 '13 at 23:52