代码之家  ›  专栏  ›  技术社区  ›  scx

区分具有相同类型和比率的std::chrono持续时间?

  •  1
  • scx  · 技术社区  · 7 年前

    我正在寻找一个强类型的解决方案 std::chrono 持续时间。我有依赖于仅运行时值的持续时间类型。我使用类似于工厂的类,使用运行时值在持续时间之间进行转换。例如:

    #include <chrono>
    #include <cstdio>
    
    using dseconds = std::chrono::duration<double>;
    using blee = std::chrono::duration<double, std::ratio<1,1>>;
    using tick = std::chrono::duration<size_t, std::ratio<1,64>>;
    
    struct converter {
        tick to_tick(dseconds s) const {
            return std::chrono::duration_cast<tick>(s / runtime_ratio);
        }
    
        tick to_tick(blee b) const {
            return std::chrono::duration_cast<tick>(b);
        }
    
    private:
        double runtime_ratio = 0.5;
    };
    
    int main(int, char**) {
        converter c;
        printf("%zu", c.to_tick(dseconds{1}).count());
        printf("%zu", c.to_tick(blee{1}).count());
    }
    

    该示例可在 compiler explorer .

    请注意,与blee的转换不同,秒的转换应用比率。由于两者都存在,因此无法编译 dseconds 和 blee 都是同一类型的。

    <source>:13:10: error: 'tick converter::to_tick(blee) const' cannot be overloaded with 'tick converter::to_tick(dseconds) const'
         tick to_tick(blee b) const {
              ^~~~~~~
    
    <source>:9:10: note: previous declaration 'tick converter::to_tick(dseconds) const'
         tick to_tick(dseconds s) const {
              ^~~~~~~
    

    我曾尝试使用模板化名来区分blee,但没有成功。我曾尝试在其他名称空间或结构中嵌套别名,但也不起作用。我读 fluentc++ 这篇文章是关于类似的东西的,但我不理解它,而且api真的很难看,而且很侵入。

    有没有一种方法可以使用相同的类型和比率来强类型2持续时间别名?

    2 回复  |  直到 7 年前
        1
  •  4
  •   Lightness Races in Orbit    7 年前

    我再提一次: .

    现在的问题是通过使用类型别名 using . 这不会创建新类型,只会为旧类型创建新名称。您试图用同一类型重载两次,这是毫无意义和不可能的,因为重载并不关心新名称。

    但是 继承创建类型 . 这是它的工作;这就是它的目的。

    有了这个,你可以很容易地创建一个有时被称为“强类型定义”(StrongTypeDef)的东西——一个新的、独特的类型,否则它的行为与你正在派生的东西非常相似。

    它确实需要少量的体操,但最终的结果是相当性感的,并且可以通过另外半个小时的工作来改善。(例如,向上转换ctor中的一点移动语义可能不会有什么影响…)。

    我们开始:

    #include <chrono>
    #include <cstdio>
    
    using dseconds = std::chrono::duration<double>;
    
    struct blee : std::chrono::duration<double, std::ratio<1,1>>
    {
        using DurationType = std::chrono::duration<double, std::ratio<1,1>>;
        using DurationType::DurationType;
        blee(const DurationType& other) : DurationType(other) {}
    };
    
    struct tick : std::chrono::duration<size_t, std::ratio<1,64>>
    {
        using DurationType = std::chrono::duration<size_t, std::ratio<1,64>>;
        using DurationType::DurationType;
        tick(const DurationType& other) : DurationType(other) {}
    };
    
    struct converter {
        tick to_tick(dseconds s) const {
            return std::chrono::duration_cast<tick::DurationType>(s / runtime_ratio);
        }
    
        tick to_tick(blee b) const {
            return std::chrono::duration_cast<tick::DurationType>(b);
        }
    
    private:
        double runtime_ratio = 0.5;
    };
    
    int main(int, char**) {
        converter c;
        printf("%zu", c.to_tick(dseconds{1}).count());
        printf("%zu", c.to_tick(blee{1}).count());
    }
    

    live demo )

    duration_cast 打个电话。

    但老实说,要得到一个不依赖黑客的解决方案,这似乎是一个很小的代价!

    blee ,但为了对称,我对两者都做了。这比离开好还是坏 tick 因为简单类型别名由读者决定。)

        2
  •  2
  •   scx    7 年前

    好吧,我已经想出了一些办法。如果你使用 std::ratio<2,2> ,相当于 std::ratio<1,1> dseconds blee 作为不同的类型。

    如果有人有更好的解决办法,我会继续提问。

    #include <chrono>
    #include <cstdio>
    
    using dseconds = std::chrono::duration<double>;
    using blee = std::chrono::duration<double, std::ratio<2,2>>;
    using tick = std::chrono::duration<size_t, std::ratio<1,64>>;
    
    struct converter {
        tick to_tick(dseconds s) const {
            return std::chrono::duration_cast<tick>(s / runtime_ratio);
        }
    
        tick to_tick(blee b) const {
            return std::chrono::duration_cast<tick>(b);
        }
    
    private:
        double runtime_ratio = 0.5;
    };
    
    int main(int, char**) {
        converter c;
        printf("%zu", c.to_tick(dseconds{1}).count());
        printf("%zu", c.to_tick(blee{1}).count());
    }
    

    compiler explorer