2016-11-05 31 views
3

我有兩個元組,一個包含值和另一個包含這些值的動作的元組。 現在我想對每個值應用相應的操作,儘可能少的代碼「開銷」。 就像下面的簡單例子。如何在數組元組上應用一個動作元組?

#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內容的地方。

有沒有辦法在適當位置修改數字?

+1

當你說「到位」,你的意思是「在'handlers_and_nums'」,或者你的意思是「在'nums'」?如果是後者,你可以創建一個'handlers_and_pointers_to_nums'而不是間接通過指針? (請記住:「計算機科學中的任何問題都可以通過另一個間接層面來解決(除了太多的間接層面)」) –

回答

3

你可以使用zip_with,但它似乎是針對其性質(它需要的功能,以實際返回的東西,但你的運營商()返回任何結果:

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