C++ 如何对派生类使用“duration\u cast”?

C++ 如何对派生类使用“duration\u cast”?,c++,c++11,chrono,C++,C++11,Chrono,我正在用std::chrono清理我的计时器类。除了我似乎无法将duration_cast应用于派生类之外,其他一切都进行得很顺利。好吧,我用另一种方式工作,但我仍然想知道我错过了什么 有关错误消息,请参阅 #include <iostream> #include <chrono> typedef std::chrono::high_resolution_clock Clock; class Milliseconds : public std::chrono::mil

我正在用std::chrono清理我的计时器类。除了我似乎无法将duration_cast应用于派生类之外,其他一切都进行得很顺利。好吧,我用另一种方式工作,但我仍然想知道我错过了什么

有关错误消息,请参阅

#include <iostream>
#include <chrono>

typedef std::chrono::high_resolution_clock Clock;

class Milliseconds : public std::chrono::milliseconds
{
public:
    typedef std::chrono::milliseconds Base;
    typedef Base::rep Type;

    using Base::Base;
};

inline Milliseconds::Type millisecondsSinceEpoch()
{
    return std::chrono::duration_cast<Milliseconds::Base>(Clock::now().time_since_epoch()).count();
    //duration_cast<Milliseconds> ERROR!
}

int main() {
    using namespace std;
    cout << millisecondsSinceEpoch() << endl;
    return 0;
}

Visual C++ 2015 RC在将代码中的DuroType强制转换为:

时,出现以下错误
error C2770: invalid explicit template argument(s) for 'enable_if<std::chrono::_Is_duration<_Ty>::value,_To>::type std::chrono::duration_cast(const std::chrono::duration<_Rep,_Period> &)'
备注:除非ToDuration是duration的实例化,否则此函数不应参与重载解析

从函数调用[14.8.2.1]的参数类型推断模板参数时,考虑基类模板专门化,但在将参数与类模板部分专门化[14.5.5.1]匹配时,不考虑基类模板专门化,这就是“持续时间”特质所发生的情况。

标准持续时间施法只能用于转换为持续时间的特殊化。[time.duration.cast]/p1:

备注:除非ToDuration是duration的实例化,否则此函数不应参与重载解析


如果ToDuration不是duration的专门化,则SFINAE或类似技术会从重载解析中删除签名,并且调用失败,除非另一个名为duration\u cast的函数模板可用。

您需要提供自己的duration\u cast


不允许将其放入命名空间std::chrono中,因此不能将其称为std::chrono::duration\u cast。一种替代方法是使用std::chrono::duration_cast和my_namespace::duration_cast添加到您的名称空间中,并使用该名称空间来限定调用。在本例中,您没有使用名称空间,因此只需要使用std.。

您会得到什么错误?@SamiKuhmonen ADL只会在值属于该名称空间的类型时找到它,而OP的示例中不是这样。此外,该调用使用显式模板参数,因此,为了将其解析为模板id,必须首先为具有该名称的函数模板声明一个声明,以供正常的非限定查找使用,否则它将无法进入ADL阶段。@bogdan ADL还会在与显式模板参数关联的命名空间中查找函数。是的,确实需要有一个可用于非限定查找的声明。使用从std或其自己的实用程序库导入的声明就足够了;不是模板id中的那些,模板id是函数调用的后缀表达式。如果函数参数的类型是类模板专用化,则ADL会在与该模板专用化的模板参数关联的命名空间中查找函数;在所有类型的其他构造中,但都与函数参数的类型有关。[3.4.2p2]:[…]名称空间和类的集合完全由函数参数的类型和任何模板参数的名称空间决定。[…]@bogdan检查该段的结尾:另外,如果前面提到的重载函数集是用模板id命名的,其关联的类和名称空间还包括其类型模板参数和模板模板-参数的类和名称空间。上述重载函数集引用了上面的句子:此外,如果参数是一组重载函数和/或函数模板的名称或地址[…]。它仍然是关于函数参数,而不是函数调用本身中的名称。写一个简单的测试,你会发现它不起作用我记得不久前在三个不同的编译器上测试过它。
template <class ToDuration, class Rep, class Period>
  constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
template <class ToDuration, class Rep, class Period>
constexpr ToDuration duration_cast(const duration<Rep, Period>& d);
template< typename my_dest, typename my_source >
my_dest duration_cast( my_source const & value )
    { return duration_cast< my_dest::duration >( value ); }