8

Perhaps an oxymoronic question: ratio<,> is, by definition, a compile-time constant.

However, I would like to construct durations with different ratios that can be specified by the caller of my method. I'm guessing I should be using something other than ratio and/or duration, then, but what?

I want to have, say, a class member that can be set at runtime, and I would like it to be of type ratio<,>. At some point in the code, where this member gets set/assigned, it would be assigned a constant ratio, but in my class, I don't want to specify what that ratio should be.

VLL
  • 9,634
  • 1
  • 29
  • 54
Tatiana Racheva
  • 1,289
  • 1
  • 13
  • 31
  • Can you include some code? I feel like I understand the gist of your question but it's quite unclear – Rerito Jun 14 '18 at 06:09
  • 1
    I assume by "can be specified by the caller" you mean that the ratio is specified during runtime? That would make a huge difference - otherwise construction the ratio is rather trivial (just set the template parameters accordingly). – andreee Jun 14 '18 at 06:15
  • Why not just have the ratio as arguments? Or keep a struct around with the ratio defined? – Clearer May 22 '19 at 20:57
  • @Clearer, when you say "ratio as arguments", do you mean, not using `ratio<,>` at all? I couldn't do that because the code that uses it requires a ratio (e.g., `duration<,,>`, etc. - see the example in https://en.cppreference.com/mwiki/index.php?title=cpp/chrono/duration#Example). Not sure about keeping the struct around. The whole point, it seems, is that the ratio must be constant, but that means durations must be constant, etc., etc. Not very flexible. – Tatiana Racheva May 27 '19 at 18:26
  • Yes, I meant not using `ratio<,>`. Durations do not have to be constant, just because their types are. – Clearer Jun 08 '19 at 08:00

2 Answers2

10

Ok, you need a std::ratio which "can be specified by the caller". There are three different options:

  • The caller wants to set std::ratio template parameters during compile time. This is trivial, simply set the parameters, e.g. using quarter = std::ratio<1, 4>.
  • The caller wants to set std::ratio template parameters during runtime. This is not possible by definition, std::ratio is a compile-time constant. You will have to implement your own class for computing ratios during runtime or use some kind of library (I don't know of any, suggestions welcome!).
  • The caller merely wants to scale a std::duration (which is what you seem to use your std::ratio for). Then just multiply it with a number.
andreee
  • 4,459
  • 22
  • 42
  • I want something in-between: I want to have, say, a class member that can be set at runtime, and I would like it to be of type ratio<,>. At some point in the code, where this member gets set/assigned, it would be assigned a constant ratio, but in my class, I don't want to specify what that ratio should be. – Tatiana Racheva Jun 14 '18 at 06:32
  • Unfortunately, that doesn't make a difference to the second option, if I understood you correctly. It doesn't matter whether your ratio is constant or not throughout runtime, it won't be a compile-time constant if you can set it/assign to it _after_ compilation (of course :-)). – andreee Jun 14 '18 at 06:37
  • 1
    As I said, I would go with some kind of ratio class that you can populate at runtime. That's the only option you have. Unfortunately I don't know of any library providing such a class and googling for "C++ ratio" isn't really helpful, as you can image... – andreee Jun 14 '18 at 06:38
  • Hmm, I'll have to think of some other way to solve my problem, then. Thanks! – Tatiana Racheva Jun 14 '18 at 06:43
  • 1
    @TatianaRacheva, I updated my answer. It just crossed my mind after your update that you might simply want to scale your time duration? – andreee Jun 14 '18 at 06:44
  • Ah, that might actually be what I need! I don't think I really need an arbitrary ratio/duration. Thanks again. – Tatiana Racheva Jun 14 '18 at 07:02
4

The answer illustrates a common approach with C++ templates:

template<typename ratio_type>
returnvalue function_name(ratio_type const& r, other parameter...)
{ ... }

The point is, that the very type of the ratio contains information. Since types (often, but not always) are the parameters passed to templates, you forward those parameters via templates, too. Of course, this only shifts the problem to a different place, so at some point you will take the numerator and denominator from the ratio and use it as values.

BTW: Consider std::div (http://en.cppreference.com/w/cpp/numeric/math/div) as alternative.

Ulrich Eckhardt
  • 16,572
  • 3
  • 28
  • 55