1

関数へのポインターに慣れていないため、現在いくつかのテストを行っています。しかし、次のプログラムでは、なぜ最初のバージョンが動作し、2 番目のバージョンがコンパイルされないのかがわかりません。正しい構文は何ですか?

#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)>'
4

1 に答える 1

3

関数ポインターは、私が変換コンテキストと呼ぶものを提供します。どのオーバーロードが意図されているかを明示的に示していますが、そうではありstd::functionません。のコンストラクターstd::functionは、任意の呼び出し可能なエンティティを取得するため、どのオーバーロードが意図されているかを明確にするためのコンテキストを提供しません。この質問も参照してください。

手動で曖昧さをなくすには、関数ポインタをキャストします

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

または名前付き関数ポインタを使用します

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

またはラムダを使用する

apply2(v, [](double* f, double* l, double d){ std::iota(f, l, d); });
于 2012-11-05T04:31:10.047 に答える