std :: chrono :: duration和自定义类型的运算符/,带有clang

时间:2019-03-14 16:41:18

标签: c++ clang chrono

考虑一个自定义类型,该类型用于对持续时间的特定实例进行乘除运算:

#include <chrono>
#include <iostream>

class Foo {};

using Duration = std::chrono::seconds;

inline Duration operator*(Duration d, Foo) {
    std::cout << "multiplying some time with Foo\n";
    return d;
}

inline Duration operator/(Duration d, Foo) {
    std::cout << "dividing some time by Foo\n";
    return d;
}

int main() {
    Duration d;
    Foo f;
    d * f;
    d / f;
}

此代码使用gcc编译时不会发出警告,但使用clang(wandbox)时失败

In file included from prog.cc:1:
/opt/wandbox/clang-7.0.0/include/c++/v1/chrono:1259:81: error: no type named 'type' in 'std::__1::common_type<long long, Foo>'
                          typename common_type<typename _Duration::rep, _Rep2>::type>::value>
                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~
/opt/wandbox/clang-7.0.0/include/c++/v1/chrono:1272:7: note: in instantiation of default argument for '__duration_divide_imp<std::__1::chrono::duration<long long, std::__1::ratio<1, 1> >, Foo>' required here
    : __duration_divide_imp<duration<_Rep1, _Period>, _Rep2>
      ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/opt/wandbox/clang-7.0.0/include/c++/v1/chrono:1279:10: note: in instantiation of template class 'std::__1::chrono::__duration_divide_result<std::__1::chrono::duration<long long, std::__1::ratio<1, 1> >, Foo, false>' requested here
typename __duration_divide_result<duration<_Rep1, _Period>, _Rep2>::type
         ^
prog.cc:22:7: note: while substituting deduced template arguments into function template 'operator/' [with _Rep1 = long long, _Period = std::__1::ratio<1, 1>, _Rep2 = Foo]
    d / f;

请注意,operator*在两种编译器中都可以正常工作。

使用在类作用域类型中定义的friend方法,实际的代码更加复杂,该方法对持续时间执行溢出安全的整数运算,但显示出完全相同的症状。

问题看起来类似于:User-defined overloaded operator * with std::chrono::duration,但这是不同的运算符和编译器。

1 个答案:

答案 0 :(得分:9)

在我看来,这似乎是一个libc ++错误(也是我写的一个错误)。这是一个经过严格测试的修复程序:

BQUEUE::~BQUEUE() {
    if ( front )
    {
        bqnode *current = front;  
        while (current->next != front)
            Dequeue();
    }
}