2016-11-05 8 views
3

私は2つのタプルを持っています。一つは値を含み、もう一つはこれらの値のアクションを含むタプルです。 これで、できるだけコードの「オーバーヘッド」を少なくして、各値に対応するアクションを適用したいと考えています。 次のような単純な例のようなものです。タプルの数でアクションのタプルを適用するには?

#include <iostream> 
#include <boost/hana.hpp> 

namespace hana = boost::hana; 
using namespace hana::literals; 


struct ThinkPositive 
{ 
    void operator()(int &val) const 
    { 
     std::cout << "Think positive!\n"; 
     val = std::abs(val); 
    } 
}; 

struct Nice 
{ 
    void operator()(int &val) const 
    { 
     std::cout << val << " is nice!\n"; 
    } 
}; 

void numbers() 
{ 
    auto handlers = hana::make_tuple(Nice{}, ThinkPositive{}); 
    auto nums = hana::make_tuple(5, -12); 
    auto handlers_and_nums = hana::zip(handlers, nums); 

    hana::for_each(handlers_and_nums, [](auto &handler_num) { 
     handler_num[0_c](handler_num[1_c]); 
    }); 

    auto result = hana::transform(handlers_and_nums, [](const auto &handler_num) { 
     return handler_num[1_c]; 
    }); 

    hana::for_each(result, [](const auto num) { 
     std::cout << "got " << num << '\n'; 
    }); 
} 

int main() 
{ 
    numbers(); 
} 

上記の例では、場所にNUMSの内容を変更することがよりよいだろう動作しますが。

numを適切に修正する方法はありますか?

あなたが zip_withを使用することができ
+1

あなたは "場所に" と言うとき、あなたは "handlers_and_nums''で" 意味ですか、またはあなたが "nums' 'で" 意味ですか?後者の場合は、代わりに 'handlers_and_pointers_to_nums'を作成し、ポインタを介して間接的に作成できますか? (覚えていること: "コンピュータサイエンスの問題は、別のレベルの間接指示(間接指示のレベルが多すぎる場合を除きます)によって解決できます)" –

答えて

3

が、()戻り、何も(それが実際に何かを返すように機能を必要とし、その性質に対してであるように思わないが、あなたの事業者:

auto special_compose = [](auto&& l, auto&& r){ l(r); return 0; }; 
hana::zip_with(special_compose, handlers, nums); 

demo


の場合あなたはオペレータが何かを返すようにすることができます。lockstep

hana::fuse(hana::fuse(hana::lockstep(hana::always(0)))(handlers))(nums); 

demo

は、外fコールなしで定義されたlockstepのようなものがあるはずですが、私はドキュメントでは何も見つかりませんでした。


もう少し標準溶液(可能な限り少ないコードオーバーヘッドのあなたの条件に適合しません):

template<typename Fs, typename Params, size_t... is> 
void apply_in_lockstep_impl(Fs&& fs, Params&& ps, std::index_sequence<is...>){ 
    int x[] = { (fs[hana::integral_c<size_t,is>](ps[hana::integral_c<size_t,is>]),0)... }; 
} 

template<typename Fs, typename Params> 
void apply_in_lockstep(Fs&& fs, Params&& ps){ 
    static_assert(hana::size(fs) == hana::size(ps), ""); 
    apply_in_lockstep_impl(std::forward<Fs>(fs), 
          std::forward<Params>(ps), 
          std::make_index_sequence<decltype(hana::size(ps))::value>{}); 
} 

が、呼び出しサイトでそれはきれいです:

apply_in_lockstep(handlers, nums); 

demo


コメントで指摘したように、別のレベルの間接指示も役立ちます。 これは、シーケンスをポインタのシーケンスに変換することを意味します。これを介して元の値が変更されます。

auto nums_ptr = hana::transform(nums, [](auto &num) { return &num; }); 
auto handlers_and_nums = hana::zip(handlers, nums_ptr); 
hana::for_each(handlers_and_nums, [](auto &handler_num) { 
    handler_num[0_c](*handler_num[1_c]); 
}); 

demo


別の、より "伝統的な"、道は範囲を反復することです。 これは、古いforループを使用する場合と同じです。

auto indices = hana::make_range(0_c, hana::length(handlers)); 
hana::for_each(indices, [&](auto i) { 
    handlers[i](nums[i]); 
}); 

demo

関連する問題