1

for_eachなどのc++STLアルゴリズムをより多くの引数で機能させるために、ここでオーバーロードが機能します。

    template<typename II1, typename II2, typename F>
F for_each( II1 _ii1, II1 ii1_, II2 _ii2, F f )
{
    while ( _ii1 != ii1_ )
    { f( *_ii1++, *_ii2++ ); }

    return f;
}

template<typename II1, typename II2, typename II3, typename F>
F for_each( II1 _ii1, II1 ii1_, II2 _ii2, II3 _ii3, F f )
{
    while ( _ii1 != ii1_ )
    { f( *_ii1++, *_ii2++, *_ii3++ ); }

    return f;
}

template<typename II1, typename II2, typename II3, typename II4, typename F>
F for_each( II1 _ii1, II1 ii1_, II2 _ii2, II3 _ii3, II4 _ii4, F f )
{
    while ( _ii1 != ii1_ )
    { f( *_ii1++, *_ii2++, *_ii3++, *_ii4++ ); }

    return f;
}

しかし、可変個引数テンプレートを使用してこの種の関数を実装する方法はありますか?

私はそれをこのように機能させることしかできません

void increase(){}

template< typename II1, typename ... IIn >
void increase( II1& _ii1, IIn& ... _iin )
{
    ++_ii1;

    increase( _iin... );
}

template<typename F, typename II1, typename ... IIn >
F for_each( F f, II1 _ii1, II1 ii1_, IIn ... _iin )
{
    while ( _ii1 != ii1_ )
    {
        f( *_ii1, *_iin ... );
        increase( _ii1, _iin... );
    }

    return f;
}

#include <iostream>
int main()
{
    int A[10];
    int B[10];
    int i = 0;
    for_each( [&i]( int & v ) { v = i++; }, A, A+10 );
    for_each( []( int a, int & b ) { b = a; }, A, A+10, B );

    for ( int i = 0; i != 10; ++i )
    { std::cout << A[i] << "\t" << B[i] << "\n"; }

    return 0;
}

これは非常に醜いです。

編集:(金6月22日21:12:28CEST2012)

これを操作するには、次のようなコードを作成する必要があります。

for_each( function, begin1, end1, begin2, begin3 );

stlの方法が好まれますが:

for_each( begin1, end1, begin2, begin3, function );

編集:(金6月22日23:55:27CEST2012)

@Hurkylの助けを借りて、今私はこれらのコードを機能させています:

namespace for_each_impl_private
{
template< typename F, typename InputIterator1, typename ... InputIteratorn >
F _for_each( F f, InputIterator1 begin1, InputIterator1 end1, InputIteratorn ... beginn )
{
    while ( begin1 != end1 )
        f( *begin1++, *beginn++... );
    return f;
}

struct dummy {};

template< typename S, typename ... T >
void rotate_then_impl( S s, T ... t )
{
    rotate_then_impl( t..., s );
}

template< typename S, typename ... T>
void rotate_then_impl( S s, dummy, T ... t )
{
    _for_each( s, t... );
}

}//namespace for_each_impl_private
template< typename ... T >
void for_each( T ... t )
{
    static_assert( sizeof ... ( t ) > 2, "for_each requires at least 3 arguments" );
    for_each_impl_private::rotate_then_impl( t..., for_each_impl_private::dummy() );
}

#include <iostream>
int main()
{
    int A[10];
    int B[10];
    int i = 0;
    for_each( A, A + 10, [&i]( int & v ) { v = i++; } );
    for_each( A, A + 10, B, []( int a, int & b ) { b = a; } );
    for_each( A, A + 10, B, []( int a, int b ) { std::cout << a << "\t" << b << "\n"; } );

    return 0;
}
4

2 に答える 2

3

ここで行ったように、パラメーター自体ではなく式を展開できます

*_iin ... 

その意味は

それぞれ_iin_kから_iin逆参照を実行し、操作の結果を関数に入れます

ただし、ここではすべての式を使用できるため、次のように記述できます。

*_iin++...
于 2012-06-22T16:11:31.753 に答える
1

これをテストするのに便利なコンパイラはありませんが、次のようなことができるはずです。

class dummy {};

template< typename S, typename T...>
void inner_func(S s, T... t);

template< typename S, typename T...>
void rotate(S s, T... t)
{
    rotate(t..., s);
}

template< typename S, typename T...>
void rotate(S s, dummy, T... t)
{
    inner_func(s, t...);
}

template< typename T...>
void outer_func(T... t)
{
   rotate(t..., dummy());
}

基本的に、左回転を繰り返すことで、引数を 1 か所右に回転させます。ただし、おそらく別のことを行う必要があります。例えば、

auto i = zip(i1_start, i2, i3, i4, i5);
for_each(i, i.end(i1_end), unzipper(function));

これにより、通常の を使用できるようになり、 andを他の目的にfor_each再利用できます。おそらくさらに良いのは、これを可能にするものを書くことです:zipunzipper

for(auto &x : zip_view(i1_start, i1_end, i2, i3, i4, i5) {
    unzip(function, x);
}
于 2012-06-22T20:14:54.993 に答える