wrapping template function and <unresolved overloaded function type

纵饮孤独 提交于 2019-12-07 16:40:52

问题


I have problem with my wrapping function.

template <typename Iter, typename SomeFunction>                         
void wrap(Iter first, Iter last, SomeFunction someFunction)
{
  someFunction(first, last);
}

I would like to use it like this:

template <typename Iter>
void fill5(Iter first, Iter last)
{
    fill(first, last, 5); 
}
int main()
{
    vector<int> v(100, -1);
    wrap(v.begin(), v.end(), fill5);

}

But I get

test.cpp: In function ‘int main()’:
test.cpp:16:40: error: no matching function for call to ‘wrap(std::vector<int>::iterator, std::vector<int>::iterator, <unresolved overloaded function type>)’
test.cpp:16:40: note: candidate is:
wrap.h:6:6: note: template<class Iter, class SomeFunction> void wrap(Iter, Iter, someFunction)

I know that if I will call that function like this

wrap(v.begin(), v.end(), fill5< vector<int>::iterator> );

it will compile. But do I always have to do it explicit? It's sucks. Why compiler can't deduce which function will be used? Is there any possibility to write wrap function to take arguments like in the first one?


回答1:


Because fill is a template function, there are basically an infinite number of overloads and the compiler does not know which one to choose.

If you declared your second template parameter to describe a function that took 2 parameters of type Iter it could then deduce it. The example below works and looks like what you want. It is not quite as generic as your attempt. It ensures the function to be called returns void and takes 2 Iter paramters.

template <typename Iter >
void wrap( Iter first, Iter last, void(*someFunction)(Iter,Iter) )
{
someFunction( first, last );
}

template <typename Iter>
void fill5(Iter first, Iter last)
{
    fill(first, last, 5); 
}

int main( int, char ** )
{
std::vector<int> v(100, -1);
wrap(v.begin(), v.end(), fill5);

return( 0 );
}



回答2:


In C++03 or C++11 there isn't much you can do about it.

fill5 is a function template, and you cannot take the address of a function template. A function template is regarded by the compiler as an infinite overload set, and requires you to specify explicitly which instance you want to take the address of:

wrap(v.begin(), v.end(), fill5<vector<int>::iterator>);
//                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Alternatively (as I mentioned in a comment to the original post, and as other answers suggest) you could use a functor with a templated call operator to wrap the invocation of fill5.

In C++14, however, we can do something better: we can use generic lambdas to simplify things a bit. If you define this macro:

#define WRAP(f) \
    [&] (auto&&... args) -> decltype(auto) \
    { return f (std::forward<decltype(args)>(args)...); }

You can then write:

int main()
{
    std::vector<int> v(100, -1);
    wrap(v.begin(), v.end(), WRAP(fill5));
}

Here is a live example.




回答3:


An alternative is to use a functor:

class fill5
{
public:
    template <typename Iter>
    void operator () (Iter first, Iter last) const
    {
        std::fill(first, last, 5); 
    }
};

int main( int, char ** )
{
    std::vector<int> v(100, -1);

    wrap(v.begin(), v.end(), fill5);
    return 0;
}


来源:https://stackoverflow.com/questions/20809686/wrapping-template-function-and-unresolved-overloaded-function-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!