7

これが私のC++コードです(私はVisual C ++ 2010を使用しています):

int absd(int t)
{
    return abs(t);
}
int main()
{
    try
    {
        int dpi = 137;
        int dpiCriterionAry[] = {100, 150, 200, 300, 400, 500, 600};
        std::vector<int> vec(dpiCriterionAry, dpiCriterionAry + _countof(dpiCriterionAry));
        std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus<int>(), dpi));
        std::transform(vec.begin(), vec.end(), vec.begin(), absd);
        //std::transform(vec.begin(), vec.end(), vec.begin(), abs);
        copy(vec.begin(), vec.end(), ostream_iterator<int>(cout, "\t"));
        cout << endl;
    }
    catch(exception& e)
    {
        cerr << e.what() << endl;
    }
    return 0;
}

行のコメントを外すと:

//std::transform(vec.begin(), vec.end(), vec.begin(), abs);

エラーメッセージが表示されました:

1>------ Build started: Project: Console, Configuration: Release Win32 ------ 
1>Build started 2012/10/16 21:17:19. 1>InitializeBuildStatus: 1>  Creating "..\Intermediate\Console.unsuccessfulbuild" because "AlwaysCreate" was specified. 1>ClCompile: 1>  Console.cpp
1>Console.cpp(16): error C2780: '_OutIt std::transform(_InIt1,_InIt1,_InIt2,_OutIt,_Fn2)' : expects 5 arguments - 4 provided 
1>          D:\ProgramFiles\VS 2010\VC\include\algorithm(1155) : see declaration of 'std::transform'
1>Console.cpp(16): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous 
1>Console.cpp(16): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous 
1>Console.cpp(16): error C2784: '_OutIt std::transform(_InIt,_InIt,_OutIt,_Fn1)' : could not deduce template argument for '_OutIt' from 'std::_Vector_iterator<_Myvec>' 
1>          with 
1>          [ 
1>              _Myvec=std::_Vector_val<int,std::allocator<int>> 
1>          ] 
1>          D:\ProgramFiles\VS 2010\VC\include\algorithm(1051) : see declaration of 'std::transform' 
1> 
1>Build FAILED. 
1> 
1>Time Elapsed 00:00:02.48 ========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

しかし、コードの行:

std::transform(vec.begin(), vec.end(), vec.begin(), absd);

働ける。実際、私が使用しているのは同じ関数absです。、結果について混乱しています。さらに、次の2行のコードを1つにマージできるかどうかを知りたいです(つまりstd::transform、同じ効果を持つ1つの呼び出しです)。

std::transform(vec.begin(), vec.end(), vec.begin(), std::bind1st(std::minus<int>(), dpi));
std::transform(vec.begin(), vec.end(), vec.begin(), absd);

誰かが2つの質問について私を助けることができますか?

4

2 に答える 2

7

問題は、std::absいくつかの過負荷があることです。std::transformそのため、コンパイラは、関数呼び出しで使用しようとしているオーバーロードを特定できません。

それを修正するために、@Xeoが彼のコメントで述べたことを行うことができます:

std::transform(vec.begin(), vec.end(), vec.begin(), [&](int i){ return abs(i); });

または、静的キャストして適切な関数アドレスを取得することもできます。

std::transform(vec.begin(), vec.end(), vec.begin(), static_cast<int(*)(int)>(abs));

最後の質問に関しては、はい、ラムダはここで魅力として機能します:

std::transform(vec.begin(), vec.end(), vec.begin(), [&](int i) { return absd(dpi - i); } );
于 2012-10-16T13:32:10.700 に答える
2

absはオーバーロードされた関数であり、単一のエンティティではありません。したがって、std::transform名前で参照される単一の関数がないため、toの呼び出しはテンプレート引数を推測できませんabs

これと同等です:

void foo(int) { }
void foo(const char*) { }

template<typename T>
int bar(T)
{ return 0; }

int i = bar(foo);  // which 'foo' ?

コンパイラにabs、意味する関数の型に明示的に変換することで、意味を伝えることができます。

std::transform(vec.begin(), vec.end(), vec.begin(), (int (*)(int))abs);

または、必要な関数を参照する変数を作成します。

int (*p)(int) = abs;
std::transform(vec.begin(), vec.end(), vec.begin(), p);

2つの変換を1つに組み合わせるには、Xeoが提案するようにラムダを使用するか、egを使用しますstd::bind

using std::placeholders::_1;
int (*p)(int) = abs;
std::transform(vec.begin(), vec.end(), vec.begin(),
               std::bind(p, std::bind(std::minus<int>(), dpi, _1)));

または、C++03の場合は代わりに使用できますboost::bind

于 2012-10-16T13:34:22.977 に答える