jjzjj

c++ - 用户定义的重载运算符 * 与 std::chrono::duration

coder 2024-02-22 原文

我创建了一个 Frequency 类模板,旨在与 std::chrono::duration 结合使用. Frequency 对象存储每单位持续时间的周期数(两者都使用其类型的模板参数)。这个想法是将频率乘以持续时间产生一个 Rep 类型的对象。这是类定义。除了相关成员,我已经省略了所有成员。

#include <ratio>
#include <chrono>
using namespace std::chrono;

template <typename Rep, typename Period = std::ratio<1>>
class Frequency
{
public:
    explicit Frequency(Rep cycles) : _cycles{cycles} { }

    friend Rep operator *(const Frequency<Rep, Period>& f, const duration<Rep, Period> d)
    {
        return f._cycles * d.count();
    }
    friend Rep operator *(const duration<Rep, Period> d, const Frequency<Rep, Period>& f)
    {
        return f._cycles * d.count();
    }
private:
    Rep _cycles; ///> The number of cycles per period.
};

问题(我认为)是 std::chrono::duration 也重载了 * 运算符,如下所示:

template< class Rep1, class Period, class Rep2 >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
    constexpr operator*( const duration<Rep1,Period>& d,
                         const Rep2& s );

template< class Rep1, class Rep2, class Period >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
    constexpr operator*( const Rep1& s,
                         const duration<Rep2,Period>& d );

根据 cppreference , 这些方法中的每一个

Converts the duration d to one whose rep is the common type between Rep1 and Rep2, and multiplies the number of ticks after conversion by s.

我相信编译器正在尝试使用这些重载的运算符模板而不是我的重载。当我编写以下代码时:

Frequency<double> f{60.0};
duration<double> d{1.0};
double foo = f * d;

我在 VS2013 中遇到类似以下错误:

C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\INCLUDE\type_traits(1446) : error C2446: ':' : no conversion from 'double' to 'Frequency<double,std::ratio<0x01,0x01>>'
        Constructor for class 'Frequency<double,std::ratio<0x01,0x01>>' is declared 'explicit'
        source_file.cpp(27) : see reference to class template instantiation 'std::common_type<Frequency<double,std::ratio<0x01,0x01>>,Rep>' being compiled
        with
        [
            Rep=double
        ]

而第1446行是std::common_type的VS实现。

那么,有没有办法确保调用我的重载而不是 std::chrono::duration 中的重载?我知道我可以通过不使用运算符重载并改为编写不同命名的方法来解决问题,但如果可能的话,我想更好地了解这里发生的事情。 (加上重载更方便。)

此外,如果这个问题重复,我深表歉意,但我在搜索后找不到任何类似的内容。

最佳答案

在这段代码中:

Frequency<double> f{60.0};
duration<double> d{1.0};
double foo = f * d;

编译器说“哦,我必须找到一个 operator* 接受一个 Frequency<double> 和一个 std::chrono::duration<double>operator* 有哪些可能性?它会生成一个可能性列表,主要由这两个组成:

friend Rep operator *(const Frequency<Rep, Period>& f, const duration<Rep, Period> d)
{
    return f._cycles * d.count();
}

template< class Rep1, class Rep2, class Period >
duration<typename std::common_type<Rep1,Rep2>::type, Period>
constexpr operator*( const Rep1& s,
                     const duration<Rep2,Period>& d );

然后,它会尝试准确地找出每个签名是什么。第一个是:

Rep operator *(const Frequency<Rep, Period>& f, const duration<Rep, Period> d)

然后尝试第二个结果:

error C2446: ':' : no conversion from 'double' to 'Frequency<double,std::ratio<0x01,0x01>>'
        Constructor for class 'Frequency<double,std::ratio<0x01,0x01>>' is declared 'explicit'
        source_file.cpp(27) : see reference to class template instantiation 'std::common_type<Frequency<double,std::ratio<0x01,0x01>>,Rep>' being compiled

因为它甚至无法弄清楚签名是什么,所以无法弄清楚选择哪一个,于是放弃了。我认为这是 MSVC 的 operator* 实现中的一个错误。在这种情况下。

明显的解决方法是制作 common_type<Frequency<double>,Rep>能够编译,可能通过删除 explicit对构造函数的限制。 aschepler观察到特化 common_type 可能更聪明、更有用:

namespace std {
    template <typename Rep, typename Period>
    struct common_type<Frequency<Rep,Period>, std::chrono::duration<Rep,Period>>   
    {
        typedef Rep type;
    };
    template <typename Rep, typename Period>
    struct common_type<std::chrono::duration<Rep,Period>, Frequency<Rep,Period>>   
    {
        typedef Rep type;
    };
}

关于c++ - 用户定义的重载运算符 * 与 std::chrono::duration,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24022142/

有关c++ - 用户定义的重载运算符 * 与 std::chrono::duration的更多相关文章

  1. ruby - Facter::Util::Uptime:Module 的未定义方法 get_uptime (NoMethodError) - 2

    我正在尝试设置一个puppet节点,但ruby​​gems似乎不正常。如果我通过它自己的二进制文件(/usr/lib/ruby/gems/1.8/gems/facter-1.5.8/bin/facter)在cli上运行facter,它工作正常,但如果我通过由ruby​​gems(/usr/bin/facter)安装的二进制文件,它抛出:/usr/lib/ruby/1.8/facter/uptime.rb:11:undefinedmethod`get_uptime'forFacter::Util::Uptime:Module(NoMethodError)from/usr/lib/ruby

  2. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  3. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  4. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  5. ruby - 主要 :Object when running build from sublime 的未定义方法 `require_relative' - 2

    我已经从我的命令行中获得了一切,所以我可以运行rubymyfile并且它可以正常工作。但是当我尝试从sublime中运行它时,我得到了undefinedmethod`require_relative'formain:Object有人知道我的sublime设置中缺少什么吗?我正在使用OSX并安装了rvm。 最佳答案 或者,您可以只使用“require”,它应该可以正常工作。我认为“require_relative”仅适用于ruby​​1.9+ 关于ruby-主要:Objectwhenrun

  6. ruby-on-rails - 使用 rails 4 设计而不更新用户 - 2

    我将应用程序升级到Rails4,一切正常。我可以登录并转到我的编辑页面。也更新了观点。使用标准View时,用户会更新。但是当我添加例如字段:name时,它​​不会在表单中更新。使用devise3.1.1和gem'protected_attributes'我需要在设备或数据库上运行某种更新命令吗?我也搜索过这个地方,找到了许多不同的解决方案,但没有一个会更新我的用户字段。我没有添加任何自定义字段。 最佳答案 如果您想允许额外的参数,您可以在ApplicationController中使用beforefilter,因为Rails4将参数

  7. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  8. ruby - 在 Ruby 中有条件地定义函数 - 2

    我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin

  9. ruby - 定义方法参数的条件 - 2

    我有一个只接受一个参数的方法:defmy_method(number)end如果使用number调用方法,我该如何引发错误??通常,我如何定义方法参数的条件?比如我想在调用的时候报错:my_method(1) 最佳答案 您可以添加guard在函数的开头,如果参数无效则引发异常。例如:defmy_method(number)failArgumentError,"Inputshouldbegreaterthanorequalto2"ifnumbereputse.messageend#=>Inputshouldbegreaterthano

  10. ruby - 如何在 Grape 中定义哈希数组? - 2

    我使用Ember作为我的前端和GrapeAPI来为我的API提供服务。前端发送类似:{"service"=>{"name"=>"Name","duration"=>"30","user"=>nil,"organization"=>"org","category"=>nil,"description"=>"description","disabled"=>true,"color"=>nil,"availabilities"=>[{"day"=>"Saturday","enabled"=>false,"timeSlots"=>[{"startAt"=>"09:00AM","endAt"=>

随机推荐