Closed mpusz closed 10 months ago
We should default to explicit unless proven otherwise.
But if the constructor behaves the same as quantity<U1, R1>(quantity{R2(), U2})
,
I don't see why it can't be implicit in all cases.
It'll already be as safe, and terser.
But if the constructor behaves the same as quantity<U1, R1>(quantity{R2(), U2}), I don't see why it can't be implicit in all cases.
Yes, this is precisely the case, and that is the reason why we need a friend constructor or a helper function to make it compile.
But do you think that a two-argument constructor is a better solution than a factory function here?
I think the constructor is better.
make_quantity
is really special in that it requires friendship,
but only because it can't be implemented in terms of a constructor.
I imagine the optimization by std::make_shared
can be implemented similarly with friendship,
but make_quantity
doesn't actually provide any benefit over a constructor (of which there's none).
Right now, the library exposes
make_quantity
andmake_quantity_point
factory functions to create a quantity without the use of a multiply or plus syntax. They are useful when a user does not like the alternative syntaxes or can't use them because of some ambiguities in the interface (e.g. in the case of linear algebra representation types).However, those need to be friends of our class templates, which complicates the design and introduces some awkwardness.
Maybe we should just use constructors with two arguments (value and unit)? The drawback of such a solution is that, in many cases, we will need to copy the same information twice:
However, if we want to use a different initializer or stick with CTAD, then it is not the issue anymore. Here are some use cases for all of the options:
Should such a constructor be explicit or implicit?
Please note that at least in the current library implementation, we will need to use friends as well to implement this.