3

vector<int>彼のすべての要素を実行し、選択した特定の演算子に従ってそれらを「合計」する関数を作成したいと思います。

たとえば、v1 = [3,6,7]この関数で計算できます - 3+6+7of 3-6-7of 3*6*7etc ..

このために私は -

#include <iostream>
#include <vector>

using namespace std;

#define     OPERATOR(X,Y,OP)  X #OP Y

template<T>
int allVectorWithOperator(vector<int> &myVector, T) {
    vector<int>::iterator it;
    vector<int>::iterator oneBeforeFinal;
    oneBeforeFinal = myVector.end();
    oneBeforeFinal -= 2;
    int sum = 0;
    for (it = myVector.begin(); it <= oneBeforeFinal; it++) {
        sum = OPERATOR(*(it),*(it+1),T);
    }
    return sum;

}

int main() {
    vector<int> myVector;
    myVector.push_back(3);
    myVector.push_back(6);
    myVector.push_back(7);
cout << "run over all the vector with * is :" << allVectorWithOperator(myVector,*)<<endl;
// here I want to get 3*6*7    

}

このようなテンプレートの場合はうまく制御できないため、このコードが機能しないことがわかりますが、私の目標が何であるかを理解していると思います。どうすれば正常に動作するように修正できますか?

編集:

私が得た2つの答えによると、コードセクションを-に変更しました

#include <iostream>
#include <vector>
#include <numeric>

using namespace std;

template<typename T>
int allVectorWhitOperator(vector<int> &myVector, const T& func) {
    int sum = std::accumulate(myVector.begin(), myVector.end(), 1, func);
    return sum;

}

int main() {
    vector<int> myVector;
    myVector.push_back(3);
    myVector.push_back(4);
    myVector.push_back(6);
    cout << "accumulate the vector with * is :"
            << allVectorWhitOperator(myVector, std::multiplies<int>()) << endl;

}

そして、それはうまくいきます!確かに私はgot accumulate the vector with * is :72

4

2 に答える 2

7

標準ライブラリには、すでに の操作があります。<algorithm><numeric>

使用できます

int sum = std::accumulate(MyVector.begin(), MyVector.end(), 0);

すべての要素を合計します。

(デフォルトを使用する代わりに)製品を計算したい場合はoperator+、追加のパラメーターを渡すことができます

int product = std::accumulate(MyVector.begin(), MyVector.end(), 1,
                              std::multiplies<int>());
于 2012-09-05T18:44:54.333 に答える
4

これは基本的にはstd::accumulateです。ベクトルが空でない場合、関数を次のように書き直すことができます。

template <typename C, typename F>
typename C::value_type fold(const C& container, const F& function) {
    typename C::iterator cur = container.begin();
    typename C::value_type init = *cur++;
    return std::accumulate(cur, container.end(), init, function);
}

...

int sum = fold(myVector, std::plus<int>());
int difference = fold(myVector, std::minus<int>());
int product = fold(myVector, std::multiplies<int>());

さて、あなたの実装について:

  1. 上記の例に示すように、テンプレートで型パラメーターを宣言するには、typenameorclassキーワードが必要です。template <typename T> int allVectorWithOperator( ... )

  2. 単独*では有効な構文にはなりません。ただし、C ++には、これらの演算子をラップする「関数オブジェクト」が多数用意されているため、関数表記で使用できます。例えば、

    std::multiplies<int> f; // f is a now function that multiplies 2 numbers
    int product = f(5, 7);  // p == 35;
    

    だからあなたは書くことができます:

    template<typename T>
    int allVectorWithOperator(vector<int> &myVector, T func) {
        ....
        for (it = myVector.begin(); it != oneBeforeFinal; ++ it) {
            sum = func(*it, *(it+1));
        }
    }
    

    また、いくつかのマイナーな点:(1)多くのイテレータは演算子をサポートしていないため、通常、イテレータを!=ではなくと比較します。(2)一般よりも効率的です。<=<=++itit++

  3. マクロとテンプレートはさまざまな段階で処理されます。特に、テンプレートまたは関数パラメーターをマクロに渡すことはできません。これは、テンプレートが考慮されるときにすべてのマクロがすでに評価されているためです。構文を実現するには、全体allVectorWithOperatorをマクロとして記述する必要があります。たとえば、次のようになります(C ++ 11を使用できると仮定)。

    #define allVectorWithOperator(container, binaryOp) \
        ([&]() -> std::remove_reference<decltype(*(container).begin())>::type { \
            auto&& c = (container); \
            auto cur = c.begin(); \
            auto val = *cur++; \
            auto end = c.end(); \
            while (cur != end) { val binaryOp##= *cur++; } \
            return val; \
        }())
    

    はい、それは完全な混乱なので、可能であればマクロを使用しないことをお勧めします。ところで、文字列#OPに変換することを意味OPします。本当に必要ありません#

于 2012-09-05T18:52:08.340 に答える