如何使用std::ratio模板参数声明模板函数



我试图用C++14定义三个函数,如下所示:

template <typename D = std::chrono::seconds>
typename D::rep test() {
// somethinig
}
template <std::intmax_t N, std::intmax_t D = 1, typename V = uint64_t>
V test() {
// something
}

这两个功能按预期工作。我可以把它们称为test<std::chrono::minutes>()test<60>。现在,我想定义第三个函数,它接受std::ratio作为模板参数。

template <template<std::intmax_t, std::intmax_t> class R, std::intmax_t N, std::intmax_t D, typename V = uint64_t>
V test() {
// R<N, D> should be std::ratio<N, D>
// something
}

但在这种情况下,在调用test<std::milli>()时会出现编译时错误。我认为这是因为编译器混淆了第一个函数和第三个函数。我该如何定义第三个呢?

定义一些特征来检测类型Tduration还是ratio:的特化

#include <chrono>
#include <ratio>
template<class>
struct is_duration : std::false_type { };
template<class Rep, class Period>
struct is_duration<std::chrono::duration<Rep, Period>> : std::true_type { };
template<class>
struct is_ratio : std::false_type { };
template<std::intmax_t Num, std::intmax_t Denom>
struct is_ratio<std::ratio<Num, Denom>> : std::true_type { };

然后使用enable_if根据T:的类型启用相应的功能

template<typename D = std::chrono::seconds, 
std::enable_if_t<is_duration<D>::value>* = nullptr>
typename D::rep test() {
// somethinig
}
template<typename R, typename V = uint64_t,
std::enable_if_t<is_ratio<R>::value>* = nullptr> 
V test() {
// R<N, D> should be std::ratio<N, D>
// something
}

演示。

另一个选项是标签调度:

template <typename> struct tag{};
template <typename Rep, typename Period> 
Rep test(tag<std::chrono::duration<Rep, Period>>)
{
// ...
}
template <std::intmax_t Num, std::intmax_t Denom> 
uint64_t test(tag<std::chrono::ratio<Num, Denom>>)
{
// ...
}
template <typename T> 
auto test() -> decltype(test(tag<T>{}))
{
return test(tag<T>{});
}
template <std::intmax_t N, std::intmax_t D = 1, typename V = uint64_t>
V test() {
// ...
}

最新更新