【问题标题】:How to properly take a boost::optional<std::chrono::duration> as a function parameter?如何正确地将 boost::optional<std::chrono::duration> 作为函数参数?
【发布时间】:2018-07-20 21:45:25
【问题描述】:

我需要一个函数接受boost::optional&lt;std::chrono::duration&gt;。 我希望能够通过它,例如 std::chrono::millisecondsstd::chrono::secondsboost::none

我有几个解决方案不能完全达到我想要的效果。

尝试 1:

template <class PeriodT>
void foo(boost::optional<std::chrono::duration<int64_t, PeriodT>> duration);

尝试 1 的问题:

我不能简单地传递std::chrono::duration 甚至boost::none。要通过boost::none 我必须执行以下操作:

boost::optional<std::chrono::seconds> input = boost::none;
foo(input);

我不能打电话

foo(boost::none); 

std::chrono::seconds input(10);
foo(input);

尝试 2:

void foo(boost::optional<std::chrono::milliseconds> duration);

尝试 2 的问题:

不会发生自动转换。

foo(std::chrono::seconds(10));

不会编译。

foo(std::chrono::milliseconds(10));

会编译,所以也会编译

foo(boost::none);

有什么方法可以让函数干净地接受boost::optional
任何代表/期间?

我的实际用例中的函数需要接受多个这些可选持续时间,因此默认值对我不起作用。

【问题讨论】:

  • 只使用重载?
  • @o11c 这如何解决我的问题?您是否建议我为我想使用的每个 std::chrono::duration 期间定义重载?
  • 除了std::chrono::nanoseconds 之外,您可能不需要任何具体的持续时间 - 所有其他持续时间都会转换,因为它是无损的。

标签: c++ c++11 templates boost chrono


【解决方案1】:
#include "boost/optional.hpp"
#include <chrono>
#include <iostream>

void foo(boost::optional<std::chrono::milliseconds> duration)
{
    if (duration)
        std::cout << duration->count() << "ms\n";
    else
        std::cout << "none\n";
}

void foo(std::chrono::milliseconds duration)
{
    foo(boost::optional<std::chrono::milliseconds>{duration});
}

int
main()
{
    using namespace std::chrono;
    foo(10ms);
    foo(10s);
    foo(boost::none);
}

如果您想接受 any chrono::duration&lt;Rep, Period&gt;,您需要再添加一个重载并将所有内容模板化。此外,您还需要决定 boost::none 的默认值 RepPeriod

#include "boost/optional.hpp"
#include "date/date.h"
#include <chrono>
#include <iostream>

template <class Rep, class Period>
void foo(boost::optional<std::chrono::duration<Rep, Period>> duration)
{
    using date::operator<<;
    if (duration)
        std::cout << *duration << "\n";
    else
        std::cout << "none\n";
}

template <class Rep, class Period>
void foo(std::chrono::duration<Rep, Period> duration)
{
    foo(boost::optional<std::chrono::duration<Rep, Period>>{duration});
}

void foo(boost::none_t)
{
    foo(boost::optional<std::chrono::seconds>{});
}

int
main()
{
    using namespace std::chrono;
    foo(10ms);
    foo(10s);
    foo(boost::none);
}

上面我还使用了Howard's date lib 来更轻松地打印任意持续时间:

10ms
10s
none

【讨论】:

  • 对于需要两个可选持续时间的函数,如何轻松扩展它?即foo(std::chrono::seconds(10), boost::none)foo(boost::none, std::chrono::seconds(10))foo(std::chrono::seconds(10), std::chrono::milliseconds(10))
  • 您需要使用受 SFINEA 约束的模板。这要麻烦得多,但可以避免 O(N^2) 问题。就我个人而言,我只会从具有none 语义的持续时间(例如duration::min())中选择一个值,而不是与optional 混在一起。
  • AANAE(字谜不是错误):)
  • 我不会拼写英文单词,更不用说难读的首字母缩略词了! :-)
猜你喜欢
  • 1970-01-01
  • 2016-07-20
  • 1970-01-01
  • 2013-07-27
  • 2023-01-11
  • 1970-01-01
  • 2013-06-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多