piecewise_linear_distributionSection: 29.5.9.6.2 [rand.dist.samp.pconst], 29.5.9.6.3 [rand.dist.samp.plinear] Status: New Submitter: Jonathan Wakely Opened: 2024-02-05 Last modified: 2025-10-11
Priority: 4
View all other issues in [rand.dist.samp.pconst].
View all issues with New status.
Discussion:
In the second constructor of 29.5.9.6.3 [rand.dist.samp.plinear], P1719R2 replaced:
withtemplate<class InputIteratorB, class InputIteratorW> piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW);Effects: [...] Moreover, the id-expressions
iterator_traits<InputIteratorB>::value_typeanditerator_traits<InputIteratorW>::value_typeshall each denote a type that is convertible todouble.
template<class InputIteratorB, class InputIteratorW> piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW);Mandates:
is_invocable_r_v<double, UnaryOperation&, double>istrue.Preconditions: [...]
Effects: [...]
This was a copy & paste error from the next constructor,
and was obviously not intended. There is no UnaryOperation
in that constructor.
A less obviously wrong issue is the use of double there
in the first place. Shouldn't it be RealType instead?
That seems to be incorrect throughout both
29.5.9.6.2 [rand.dist.samp.pconst]
and
29.5.9.6.3 [rand.dist.samp.plinear],
and was only partially fixed by LWG 1439.
Finally, the preconditions also say:
Preconditions: [...] IffirstB == lastBor++firstB == lastB, let n = 1, ρ0 = ρ1 = 1, b0 = 0, and b1 = 1. Otherwise, [firstB,lastB) forms a sequence b of length n + 1, the length of the sequence w starting fromfirstWis at least n, and any wk for k ≥ n are ignored by the distribution.
These are not preconditions. I think it is trying to say something like:
Preconditions: [...] [
firstB,lastB) is a valid range and [firstW,firstW + (lastB - firstB)) is a valid range.Effects: If
firstB == lastBor++firstB == lastB, let n = 1, ρ0 = ρ1 = 1, b0 = 0, and b1 = 1. Otherwise, let [firstB,lastB) form a sequence b0, …, bn, and let wk =*firstW++for k = 0, …, n.
The equivalent constructor for piecewise_constant_distribution
has similar problems with its preconditions in terms of n + 1.
[2024-03-12; Reflector poll]
Set priority to 4 after reflector poll. The copy & paste error was fixed editorially.
[2025-10-06; Hewill comments and provides wording]
We should fix the constructor, otherwise the following should be rejected according to the standard:
#include <random>
struct Op {
float operator()(float);
void operator()(auto) = delete;
};
static_assert(!std::is_invocable_r_v<double, Op&, double>);
int main() {
std::initializer_list<float> l;
std::piecewise_linear_distribution<float> dist(l, Op{});
}
This is, because it violates Mandates. However, all three compilers accept it because
Op& can take float and return float.
Proposed resolution:
This wording is relative to N5014.
Modify 29.5.9.6.2 [rand.dist.samp.pconst] as indicated:
template<class InputIteratorB, class InputIteratorW> piecewise_constant_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW);-4- Mandates: Both of
(4.1) —
is_convertible_v<iterator_traits<InputIteratorB>::value_type, result_typedouble>(4.2) —
is_convertible_v<iterator_traits<InputIteratorW>::value_type, result_typedouble>are
[…]true.template<class UnaryOperation> piecewise_constant_distribution(initializer_list<RealType> bl, UnaryOperation fw);-7- Mandates:
[…]is_invocable_r_v<result_typeisdouble, UnaryOperation&, result_typedouble>true.template<class UnaryOperation> piecewise_constant_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);-10- Mandates:
[…]is_invocable_r_v<result_typeisdouble, UnaryOperation&, result_typedouble>true.
Modify 29.5.9.6.3 [rand.dist.samp.plinear] as indicated:
template<class InputIteratorB, class InputIteratorW> piecewise_linear_distribution(InputIteratorB firstB, InputIteratorB lastB, InputIteratorW firstW);-4- Mandates: Both of
(4.1) —
is_convertible_v<iterator_traits<InputIteratorB>::value_type, result_typedouble>(4.2) —
is_convertible_v<iterator_traits<InputIteratorW>::value_type, result_typedouble>are
[…]true.template<class UnaryOperation> piecewise_linear_distribution(initializer_list<RealType> bl, UnaryOperation fw);-7- Mandates:
[…]is_invocable_r_v<result_typeisdouble, UnaryOperation&, result_typedouble>true.template<class UnaryOperation> piecewise_linear_distribution(size_t nw, RealType xmin, RealType xmax, UnaryOperation fw);-10- Mandates:
[…]is_invocable_r_v<result_typeisdouble, UnaryOperation&, result_typedouble>true.