包装模板函数和<未解析的重载函数类型

Pra*_*zek 3 c++ templates overloading function wrapper

我的包装功能有问题.

template <typename Iter, typename SomeFunction>                         
void wrap(Iter first, Iter last, SomeFunction someFunction)
{
  someFunction(first, last);
}
Run Code Online (Sandbox Code Playgroud)

我想像这样使用它:

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);

}
Run Code Online (Sandbox Code Playgroud)

但我明白了

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)
Run Code Online (Sandbox Code Playgroud)

我知道如果我会这样称呼这个功能

wrap(v.begin(), v.end(), fill5< vector<int>::iterator> );
Run Code Online (Sandbox Code Playgroud)

它会编译.但我是否总是要明确这样做?太糟糕了.为什么编译器无法推断出将使用哪个函数?是否有可能编写wrap函数来获取第一个参数?

And*_*owl 8

在C++ 03或C++ 11中,你无能为力.

fill5是一个函数模板,您不能获取函数模板的地址.编译器将函数模板视为无限重载集,并要求您明确指定要采用以下地址的实例:

wrap(v.begin(), v.end(), fill5<vector<int>::iterator>);
//                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

或者(正如我在原始帖子的评论中提到的,以及其他答案建议),您可以使用带有模板化调用运算符的仿函数来包装调用fill5.

但是,在C++ 14中,我们可以做得更好:我们可以使用通用lambdas来简化一些事情.如果您定义此宏:

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

然后你可以写:

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

这是一个实例.

  • @BrianGradin:是的.你可以调用一个通用的lambda,比如`auto lambda = [](auto x){std :: cout << x; 使用不同类型的参数,例如`lambda(42)`,`lambda("hello")`等等.使用C++ 11,您必须提交一种具体类型. (2认同)