2012-11-05 43 views
1

我不熟悉函数指针,我正在做一些测试。但在下面的程序中,我不明白为什么第一个版本能够工作,为什么第二个版本不能编译。什么是正确的语法?函数指针和std :: function:第一个编译而不是第二个?

#include <iostream> 
#include <cmath> 
#include <vector> 
#include <algorithm> 
#include <numeric> 
#include <functional> 

template<typename Type> 
void display(const std::vector<Type>& v) 
{ 
    if (!v.empty()) { 
     for (unsigned int i = 0; i < v.size()-1; ++i) 
      std::cout<<v[i]<<" "; 
     std::cout<<v[v.size()-1]; 
    } 
} 

// Compiles 
template<typename Type> 
void apply1(std::vector<Type>& v, void(f)(Type*, Type*, Type)) 
{ 
    f(&*v.begin(), &*v.end(), 0); 
} 

// Does not compile 
template<typename Type> 
void apply2(std::vector<Type>& v, std::function<void(Type*, Type*, Type)> f) 
{ 
    f(&*v.begin(), &*v.end(), 0); 
} 

int main() 
{ 
    std::vector<double> v = {1., 2., 3., 4., 5., 6.}; 
    display(v); std::cout<<std::endl; 
    apply1(v, std::iota); 
    display(v); std::cout<<std::endl; 
    apply2(v, std::iota); 
    display(v); std::cout<<std::endl; 
    return 0; 
} 

误差如下:

error: cannot resolve overloaded function 'iota' based on conversion to type 'std::function<void(double*, double*, double)>' 

回答

3

一个函数指针提供我所说的转换上下文。它明确指出哪些重载意味着什么,而std::function则不。 std::function的构造函数接受任何可调用的实体,并且因此不提供上下文来消除意味着哪种超载。另见this question

要手动消除歧义,要么投函数指针

apply2(v, static_cast<void(*)(double*,double*,double)>(std::iota)); 

或使用命名函数指针

void (*iota)(double*, double*, double) = std::iota; 
apply2(v, iota); 

或使用lambda

apply2(v, [](double* f, double* l, double d){ std::iota(f, l, d); }); 
+0

所以,我怎么可以修改'apply2 '或者其调用像'std :: iota'这样的算法? – Vincent

+0

@Vincent:编辑。 – Xeo

+0

谢谢。但我有另一个问题:在我调用函数而不是函数模板的情况下:两个实现“等价”(除了std :: function更“强大”的事实外)? – Vincent

相关问题