簡體   English   中英

返回與C ++ 17中可變參數模板相對應的元組

[英]Return a tuple corresponding to variadic template in C++17

如何從采用可變參數模板列表的函數返回元組? 元組類型應與參數類型相同。

template <typename ... T, typename D>
std::tuple<T...> foo(D&& Duration) {
  // How to do this?
  if constexpr(sizeof... (args) > 0) {
    ... 
  }
  // What to return?
}

這個想法是使用C ++ 17結構綁定,所以我可以做這樣的事情:

auto var = std::chrono::seconds(19874);

auto [h, m] = foo<std::chrono::hours, std::chrono::minutes> (var);
auto [m, s, ms] = foo<std::chrono::minutes, std::chrono::seconds, std::chrono::milliseconds>(var);

對於這兩種情況,總和(h:m或m:s:ms)應為19874秒。

此代碼應執行您的要求。 它使用對每種chrono_extract類型的chrono_extract調用的初始化列表構造元組。 初始化程序列表參數是根據標准按順序處理的,因此即使使用逗號看起來像這樣,它也不會對任何重新排序敏感。 chrono_extract函數將輸入持續時間強制轉換為輸出持續時間的類型,然后從輸入中減去輸出(該輸出通過引用傳遞,因此其值將反映在chrono_components )。 為了正確地運行算法,我們需要在列表中找到最小的時間分量,並以最小的分辨率運行所有計算(否則將存在持續時間轉換錯誤)。 還提供了一個斷言,以確保返回持續時間類型按遞減順序排列,因為如果函數按不同順序排列將無法正確運行。 可以添加的一個可能的增強功能是,如果分解中還剩下任何內容,則在元組中也返回一個“余數”(與輸入類型相同)(如下面代碼中的第一個測試用例)。

#include <chrono>
#include <iostream>
#include <tuple>
#include <type_traits>

template <typename lhs_t, typename rhs_t, typename... other_ts>
constexpr void assert_decreasing_ratios() {
    static_assert(std::ratio_greater_v<typename lhs_t::period,
                                       typename rhs_t::period>,
                  "Periods are non-decreasing.");
    if constexpr (sizeof...(other_ts)) {
        assert_decreasing_ratios<rhs_t, other_ts...>();
    }
}

template <typename return_duration_t, typename input_duration_t>
return_duration_t chrono_extract(input_duration_t& value) {
    auto extracted = std::chrono::duration_cast<return_duration_t>(value);
    value -= extracted;
    return extracted;
}

template <typename... return_ts, typename duration_t>
std::tuple<return_ts...> chrono_components(duration_t value) {
    assert_decreasing_ratios<return_ts...>();
    using smallest_t = std::tuple_element_t<sizeof...(return_ts) - 1,
                                            std::tuple<return_ts...>>;
    auto small_value = std::chrono::duration_cast<smallest_t>(value);
    return {chrono_extract<return_ts>(small_value)...};
}

int main()
{
    std::chrono::seconds before(19874);

    {
        auto [h, m] = chrono_components<std::chrono::hours,
                                        std::chrono::minutes>(before);
        std::chrono::seconds after(h + m);
        std::cout << h.count() << " hours " 
                  << m.count() << " minutes = "
                  << after.count() << " seconds\n";
    }

    {
        auto [m, s, ms] = chrono_components<std::chrono::minutes,
                                            std::chrono::seconds,
                                            std::chrono::milliseconds>(before);
        auto after =
            std::chrono::duration_cast<std::chrono::seconds>(m + s + ms);
        std::cout << m.count() << " minutes " 
                  << s.count() << " seconds " 
                  << ms.count() << " milliseconds = "
                  << after.count() << " seconds\n";
    }
}

輸出量

5 hours 31 minutes = 19860 seconds
331 minutes 14 seconds 0 milliseconds = 19874 seconds

第一行顯示秒數值已被截斷,因為它不是精確的分鍾數。

暫無
暫無

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

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