簡體   English   中英

將函數應用於元組的每個元素

[英]Applying a function to each element of a tuple

給定一個tuple_size std::tuple的對象(即使用定義的tuple_sizeget語義)和一元函子ftor ,我希望能夠在類tuple對象的每個元素上調用ftor

如果我忽略返回值,我知道int數組技巧:

namespace details {

template <typename Ftor, typename Tuple, size_t... Is>
void apply_unary(Ftor&& ftor, Tuple&& tuple, std::index_sequence<Is...>) {
    using std::get;
    int arr[] = { (ftor(get<Is>(std::forward<Tuple>(tuple))), void(), 0)... };
}

} // namespace details

template <typename Ftor, typename Tuple>
void apply_unary(Ftor&& ftor, Tuple&& tuple) {
    details::apply_unary(std::forward<Ftor>(ftor),
                         std::forward<Tuple>(tuple),
                         std::make_index_sequence<std::tuple_size<Tuple>::value> {});
}

如果我想要返回值,我可以用std::make_tuple調用替換int []技巧,然后返回。 只要沒有對ftor對象的調用都有void值返回值, ftor

因此我的問題是:考慮到我想得到調用的結果,我該如何處理可能返回void調用?

唯一的要求是我應該將結果作為元組得出,並且能夠告訴哪個調用導致所述結果的哪個元素元組。

正如@ Jarod42所建議的那樣,用一個額外的層包裝調用來處理用虛擬結構替換void返回的方法就可以了:

struct no_return {};

namespace details {

template <typename Ftor, typename Arg>
auto call(Ftor&& ftor, Arg&& arg)
    -> std::enable_if_t<std::is_void<decltype(std::forward<Ftor>(ftor)(std::forward<Arg>(arg)))>::value, no_return> {
    std::forward<Ftor>(ftor)(std::forward<Arg>(arg));
    return no_return {};
}

template <typename Ftor, typename Arg>
auto call(Ftor&& ftor, Arg&& arg)
    -> std::enable_if_t<!std::is_void<decltype(std::forward<Ftor>(ftor)(std::forward<Arg>(arg)))>::value, decltype(std::forward<Ftor>(ftor)(std::forward<Arg>(arg)))> {
    return std::forward<Ftor>(ftor)(std::forward<Arg>(arg));
}

template <typename Ftor, typename Tuple, size_t... Is>
auto apply_unary(Ftor&& ftor, Tuple&& tuple, std::index_sequence<Is...>) {
    using std::get;
    return std::tuple<decltype(call(ftor, get<Is>(std::forward<Tuple>(tuple))))...> { call(ftor, get<Is>(std::forward<Tuple>(tuple)))... } ;
}

} // namespace details

template <typename Ftor, typename Tuple>
auto apply_unary(Ftor&& ftor, Tuple&& tuple) {
    return details::apply_unary(std::forward<Ftor>(ftor),
                                std::forward<Tuple>(tuple),
                                std::make_index_sequence<std::tuple_size<std::decay_t<Tuple> >::value> {});
}

Coliru提供現場演示

我使用SFINAE來區分這兩個重載。 它看起來有點難看,所以如果你有任何改進建議......我全都耳朵!

其他方式:

namespace details {

struct apply_unary_helper_t {};

template<class T> 
T&& operator,(T&& t, apply_unary_helper_t) { // Keep the non-void result.
    return std::forward<T>(t); 
}

template <typename Ftor, typename Tuple, size_t... Is>
void apply_unary(Ftor&& ftor, Tuple&& tuple, std::index_sequence<Is...>) {
    auto r = {(ftor(std::get<Is>(std::forward<Tuple>(tuple))), apply_unary_helper_t{})...};
    static_cast<void>(r); // Suppress unused variable warning.
}

} // namespace details

template <typename Ftor, typename Tuple>
void apply_unary(Ftor&& ftor, Tuple&& tuple) {
    details::apply_unary(std::forward<Ftor>(ftor),
                         std::forward<Tuple>(tuple),
                         std::make_index_sequence<std::tuple_size<std::remove_reference_t<Tuple>>::value> {});
}

在上面,它將operator,應用於ftorapply_unary_helper_t的結果。 如果ftor的結果為void ,則rstd::initializer_list<details::apply_unary_helper_t> ,否則rstd::initializer_list<decltype(ftor(...))> ,您可以使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM