我的包装功能有问题。
template <typename Iter, typename SomeFunction>
void wrap(Iter first, Iter last, SomeFunction someFunction)
{
someFunction(first, last);
}
我想像这样使用它:
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);
}
但是我得到了
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)
我知道如果我将这样的功能称为
wrap(v.begin(), v.end(), fill5< vector<int>::iterator> );
它会编译。但我是否总是要明确这样做?太糟糕了。为什么编译器无法推断出将使用哪个函数?是否有可能编写wrap函数来获取第一个参数?
答案 0 :(得分:8)
在C ++ 03或C ++ 11中,你无能为力。
fill5
是一个函数模板,您无法获取函数模板的地址。编译器将函数模板视为无限重载集,并要求您明确指定要使用以下地址的实例:
wrap(v.begin(), v.end(), fill5<vector<int>::iterator>);
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
或者(正如我在原始帖子的评论中提到的,以及其他答案建议),您可以使用带有模板化调用运算符的仿函数来包装fill5
的调用。
然而,在C ++ 14中,我们可以做得更好:我们可以使用通用lambdas来简化一些事情。如果您定义此宏:
#define WRAP(f) \
[&] (auto&&... args) -> decltype(auto) \
{ return f (std::forward<decltype(args)>(args)...); }
然后你可以写:
int main()
{
std::vector<int> v(100, -1);
wrap(v.begin(), v.end(), WRAP(fill5));
}
这是live example。
答案 1 :(得分:3)
另一种方法是使用仿函数:
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;
}
答案 2 :(得分:1)
因为fill是一个模板函数,基本上有无限数量的重载,编译器不知道选择哪一个。
如果你声明你的第二个模板参数来描述一个带有2个Iter类型参数的函数,那么它就可以推导出它。以下示例有效,看起来就像您想要的那样。它并不像你的尝试那样通用。它确保被调用的函数返回void并且需要2个Iter参数。
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 );
}