我正在寻找针对 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 上找到.
请注意,从秒转换应用比率,这与从出血转换不同。这不会编译,因为 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,但这没有用。我试过在其他 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/