samedi 1 décembre 2018

Differentiating std::chrono durations that have the same type and ratio?

I am looking for a strongly typed solution for std::chrono durations. I have duration types that depend on a run-time only value. I use a factory-like class to convert between durations using the runtime value. For example :

#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());
}

The example is available on compiler explorer.

Notice the conversion from seconds applies the ratio, unlike the conversion from blee. This doesn't compile since both dseconds and blee are really the same type.

<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 {
          ^~~~~~~

I've tried using templated aliases to differentiate blee, but that didn't work. I've tried nesting aliases in other namespaces or structs, that didn't work either. I read fluentc++'s post about something similar, but I don't understand it and the api is really ugly and intrusive.

Is there a way to strongly type 2 duration alias with the same type and ratio?

Aucun commentaire:

Enregistrer un commentaire