2

私はC++テンプレートを読んでいます:完全なガイドブックと第4章(4.2非型関数テンプレートパラメーター)は、コレクションの各要素に値を追加するためにSTLコンテナーで使用できるテンプレート関数の例です。完全なプログラムは次のとおりです。

#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>


template<typename T, int VAL>
T addValue(T const& x)
{
    return x + VAL;
}

int main()
{
    std::vector<int> source;
    std::vector<int> dest;
    source.push_back(1);
    source.push_back(2);
    source.push_back(3);
    source.push_back(4);
    source.push_back(5);

    std::transform(source.begin(), source.end(), dest.begin(), (int(*)(int const&)) addValue<int, 5>);
    std::copy(dest.begin(), dest.end(), std::ostream_iterator<int>(std::cout, ", "));

    return 0;
}

本が次のように述べているので、私はその醜いキャストを作らなければなりませんでした:

Note that there is a problem with this example: addValue<int,5> is a function template, and function templates are considered to name a set of overloaded functions (even if the set has only one member). However, according to the current standard, sets of overloaded functions cannot be used for template parameter deduction. Thus, you have to cast to the exact type of the function template argument:

std::transform (source.begin(), source.end(),  // start and end of source 
                dest.begin(),                  // start of destination 
                (int(*)(int const&)) addValue<int,5>);  // operation 

私の問題は、プログラムの実行時にセグメンテーション違反が発生することです。MacでClangを使用してビルドしています。
キャストが間違っていますか、それとも他に何が問題である可能性がありますか?

4

2 に答える 2

3

キャストは問題ではありません。要素を空の に出力していますvector。代わりにresize、必要なスペースを確保できます。

dest.resize(source.size());

またはそれを理解させtransformてください:

std::transform(
    source.begin(), source.end()
  , std::back_inserter( dest ) // needs <iterator>
  , &addValue<int, 5> // cast should not be needed
);

ただし、必要なスペースがわかっている場合はresize、ベクトルを -ing すると、アイテムが追加される際の内部再割り当てが回避されるため、パフォーマンスが向上します。もう 1 つの方法は、reserve内部の再割り当てを回避するために呼び出すことです。

dest.reserve(source.size());
// dest is still empty

std::transform(
    source.begin(), source.end()
  , std::back_inserter( dest ) // needs <iterator>
  , &addValue<int, 5> // cast should not be needed
);
于 2012-12-30T21:23:05.567 に答える
2

セグメンテーション違反の問題は、それdestが空であるにもかかわらず、値を割り当てていることです! 実際に割り当てることができる要素があることを確認するには、2 つの方法があります。

  1. データを ing するdest前にのサイズを設定できます。std::transform()dest.resize(source.size())
  2. :をdest使用して最後にオブジェクトを挿入するようにアルゴリズムに指示できます(関数オブジェクトを取得するための適切な方法は です)。std::back_insert_iterator<...>std::transform(source.begin(), source.end(), std::back_inserter(dest), function)function

個人的には、とにかく関数へのポインターを使用しません。コンパイラーが関数へのポインターを介して関数呼び出しをインライン化しない可能性が非常に高いためです。代わりに、適切な関数オブジェクトを使用します。

template <int N>
struct addValue {
    template <typename T>
    T operator()(T value) const { return value + N; }
};

...そして、ただ使う

std::transform(source.begin(), source.end(), std::back_inserter(dest), addValue<5>());
于 2012-12-30T21:28:04.257 に答える