Closed GElliott closed 6 years ago
It's a bit different of a way to think about the problem, but this is what I prefer for your use case is to enforce the concept with a static assert:
template<class FreqUnitType>
void set_frequency(FreqUnitType frequency)
{
static_assert(units::traits::is_frequency_unit<FreqUnitType>::value,
"FreqUnitType must be a unit_t type representing a frequency value");
// ...
}
Each unit category has an associated trait. You could also use std::is_convertible_v<FreqUnitType, units::frequency::hertz_t>
.
This has the added benefit of (IMO) being more readable and obvious to what the requirement is, as well as providing a logical and succinct error message on misuse.
Another simple method is to parameterize on hertz_t
. Since all frequency units are implicitly convertible, you can mix and match them without worry:
void set_frequency(units::frequency::hertz_t frequency) { //... }
myClass.set_frequency(100_kHz); // this works fine
myClass.set_frequency(10_m); // compile error
In most situations it's not even more expensive because you could very well do a conversion to store the frequency in a member, or whatever it is you do with it.
In cases where you want to overload the function for different unit types, use the trait with an enable_if
on the return value.
That works well enough for me. Thanks!
Here is a common pattern for defining a template function that accepts
std::chrono::duration
types:I would like to do the same thing with units types. It's not clear to me how this should be accomplished. This definition partially works:
I can pass in
units::frequency::hertz_t
types to this function. However, I get a compile-time error when I try to pass inunits::frequency::kilohertz_t
(clang, Linux, 3.8):How should I define the templatized parameter
frequency
?