I need to have a function accept a boost::optional<std::chrono::duration>
.
I would like to be able to pass it, for example, either std::chrono::milliseconds
, std::chrono::seconds
, or boost::none
.
I have a couple of solutions which do not exactly achieve what I want.
Attempt 1:
template <class PeriodT>
void foo(boost::optional<std::chrono::duration<int64_t, PeriodT>> duration);
Problems with attempt 1:
I cannot simply pass an std::chrono::duration
or even boost::none
. To pass boost::none
I have to do the following:
boost::optional<std::chrono::seconds> input = boost::none;
foo(input);
I cannot call
foo(boost::none);
or
std::chrono::seconds input(10);
foo(input);
Attempt 2:
void foo(boost::optional<std::chrono::milliseconds> duration);
Problems with attempt 2:
Automatic conversion won't happen.
foo(std::chrono::seconds(10));
Will not compile.
foo(std::chrono::milliseconds(10));
Will compile, and so will
foo(boost::none);
Is there any way I can have a function cleanly accept a boost::optional
of any rep/period?
The function in my actual use case will need to accept multiple of these optional durations, so default values won't work for me.
#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);
}
If you want to accept any chrono::duration<Rep, Period>
, you need to add one more overload and template everything. Also you need to decide what Rep
and Period
you want to default to for boost::none
:
#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);
}
Above I've also used Howard's date lib for easier printing of the arbitrary durations:
10ms
10s
none