如何从一个带有可变参数模板列表的函数返回一个元组?元组类型应与参数类型相同.
template <typename ... T, typename D>
std::tuple<T...> foo(D&& Duration) {
// How to do this?
if constexpr(sizeof... (args) > 0) {
...
}
// What to return?
}
Run Code Online (Sandbox Code Playgroud)
我的想法是使用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);
Run Code Online (Sandbox Code Playgroud)
对于这两种情况,总和(h:m或m:s:ms)应为19874秒.
这段代码应该按照你的要求做.它使用chrono_extract每个ouptut类型的调用的初始化列表构造元组.初始化列表参数按照标准按顺序处理,因此对任何重新排序都不敏感,即使它可能看起来像是使用逗号.该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";
}
}
Run Code Online (Sandbox Code Playgroud)
产量
5 hours 31 minutes = 19860 seconds
331 minutes 14 seconds 0 milliseconds = 19874 seconds
Run Code Online (Sandbox Code Playgroud)
第一行显示秒值已被截断,因为它不是精确的分钟数.
| 归档时间: |
|
| 查看次数: |
539 次 |
| 最近记录: |