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

标签 c++ c++11 alias c++-chrono

我正在寻找针对 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 上找到.

请注意,从秒转换应用比率,这与从出血转换不同。这不会编译,因为 dsecondsblee 实际上是同一类型。

<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,但这没有用。我试过在其他 namespace 或结构中嵌套别名,但也没有用。我读了fluentc++关于类似内容的帖子,但我不明白,而且 api 真的很丑陋且具有侵入性。

有没有办法以相同的类型和比率强类型化 2 个持续时间别名?

最佳答案

我再次建议:使用继承

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

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

有了它,您可以轻松地创建有时被称为“强类型定义”的东西 — 一种全新的、独特的类型,在其他方面的行为与您派生的东西几乎完全一样。

它确实需要少量体操,但最终结果非常诱人,再工作半小时可能会微不足道。 (例如,在那个向上转换的 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 作为一个简单的类型别名好还是坏取决于读者。)

我什至会说这是唯一语义上“正确”的解决方案,因为您实际上是在创建语义上的新类型,而这不是别名的用途。别名用于为某些现有类型创建一个方便的替代名称。

关于c++ - 区分具有相同类型和比率的 std::chrono 持续时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53574907/

相关文章:

c++ - ncurses:是否可以在不移除边框的情况下刷新窗口?

c++ - 如何正确设置SonarQube cfamil.gcov?

macos - 如何制作接受参数并在后台执行的命令的别名?

c++ - 从 .SVG 文件创建 QIcon 后为空

c++ - 在函数指针返回值中转换对指针的引用

c++ - 使用单例分配静态成员

c++ - 分配器感知容器和 propagate_on_container_swap

sql - 我能否以向后兼容的方式更改 SQL Server 表名?例如添加一个永久别名?

c++ - 根据编译时常量,使用 #define'd 或 typedef'ed 相同的标识符是否被认为是可接受的做法?

c++ - Qt - QGraphics(形状)项目的选择