Topic: Random number engine adaptor requirements [rand.req.adapt]
Author: MiloRambaldi<james.hirschorn@gmail.com>
Date: Wed, 21 Mar 2012 11:35:52 -0700 (PDT)
Raw View
> From N3337:
-----
26.5.1.5 Random number engine adaptor requirements [rand.req.adapt]
1 A random number engine adaptor (commonly shortened to adaptor) a of type A is a random number engine that takes values produced by some other random number engine, and applies an algorithm to those values in order to deliver a sequence of values with different randomness properties. An engine b of type B adapted
in this way is termed a base engine in this context. The expression a.base() shall be valid and shall return a const reference to a s base engine.
...
-----
My question is about the interpretation of "takes values produced by some other random number engine". Must a random number engine adapter apply to *all* random number engines, or can an adapter only apply to *some* random number engines.
The motivation is the following case: We have a class of random number engines, that in addition to the standard provide some other member function to obtain random numbers. There is a useful adapter that is only relevant for this class of engines. If the adapter will only compile with engines from the class, can it still satisfy the standard?
Reading all of 26.5.1.5, my interpretation is that the answer is yes. There is nothing in the standard explicitly stating that an adapter must obtain values from the base engine through its operator()() member.
--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: =?windows-1252?Q?Daniel_Kr=FCgler?=<daniel.kruegler@googlemail.com>
Date: Thu, 22 Mar 2012 11:23:45 -0700 (PDT)
Raw View
Am 21.03.2012 19:35, schrieb MiloRambaldi:
> My question is about the interpretation of "takes values produced by some other random number engine". Must a random number engine adapter apply to *all* random number engines, or can an adapter only apply to *some* random number engines.
In my opinion you are talking about two issues:
1) The most simple one is your last question: The answer is trivial:
Every requirement set can be refined to an arbitrary degree of
constraints. Given that fundamental property of refinements of concepts
there is no point that you can define your own random number engine
adaptor that accepts only a restricted set of engines (and the
restrictions can be defined by your-self).
2) Nonetheless I think that you are asking an interesting question in
regard to what the library specification describes. It is a fact that
all specialized library-defined engine adaptors do refer to evaluating
the expression e() given its engine(s) e in some way. This is to be
expected given the "interface" of general random number engines. From
the perspective of the standard, there does not exist any engine concept
which provides another way of reading the generated values of it's state
except from a function call expression without parameters. So unless you
can point out that from a user point of view it is unclear what a
standard engine adaptor will do with your provided engine I cannot yet a
defect from the current state.
I would be interested to hear why your engines are designed this way.
From your description it sounds as if they are no engines at all (do
they satisfy the criteria of random number engines?). What is the reason
for these functions being involved from the engine? Couldn't these
functions be provided by an additional policy of the adaptor that would
not intrusively depend on special functions of the engine?
Greetings from Bremen,
Daniel Kr gler
--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: MiloRambaldi<james.hirschorn@gmail.com>
Date: Fri, 23 Mar 2012 17:10:46 -0700 (PDT)
Raw View
Hi Daniel,
Sorry but I was not asking about the right section. 26.5.1.5 is about types, whereas I was asking about engine adapter templates.
My corrected question is essentially the same:
In section 26.5.4 Random number engine adaptor class templates [rand.adapt], nothing is said about whether the random engine adapter template must accept, as a type template parameter, *all* random number engine types as in section 26.5.1.4. If a class template will only compile for a subset of all of the random number engine types, can it still satisfy the requirements of 26.5.4?
On Thursday, March 22, 2012 2:23:45 PM UTC-4, Daniel Kr gler wrote:
>
> In my opinion you are talking about two issues:
>
> 1) The most simple one is your last question: The answer is trivial:
> Every requirement set can be refined to an arbitrary degree of
> constraints. Given that fundamental property of refinements of concepts
> there is no point that you can define your own random number engine
> adaptor that accepts only a restricted set of engines (and the
> restrictions can be defined by your-self).
I think I've now clarified that (1) is not an issue?
>
> 2) Nonetheless I think that you are asking an interesting question in
> regard to what the library specification describes. It is a fact that
> all specialized library-defined engine adaptors do refer to evaluating
> the expression e() given its engine(s) e in some way. This is to be
> expected given the "interface" of general random number engines. From
> the perspective of the standard, there does not exist any engine concept
> which provides another way of reading the generated values of it's state
> except from a function call expression without parameters. ...
Yes, this is the whole point: I am assuming that an engine could provide some other way of reading generated values, in addition to those required by the standard, and still satisfy the requirements of 26.5.1.4 (yes?)
I will describe some specifics on the engine adapter template that led to my question. I have my own concept of a "reversible random number engine", refining 26.5.1.4. In addition to the requirements of a random number engine, a reversible random number engine provides a method reverse() which generates random numbers in reverse order of operator()(). Then I have an adapter template called reverse_adapter:
template<typename Engine, ...> class reverse_adapter { ... };
In general it will only compile if Engine is a reversible random number engine (i.e. has a reverse() method). (It should be obvious what the adapter does.)
My question is whether reverse_adapter can satisfy the requirements of the standard, since it will not accept all Engine types? My interpretation of the standard is yes, since there is no explicit requirement to accept all Engine types. However, I know others who have interpreted this section of the standard differently.
--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Sat, 24 Mar 2012 19:26:49 -0700 (PDT)
Raw View
Am 24.03.2012 01:10, schrieb MiloRambaldi:
>
> Sorry but I was not asking about the right section. 26.5.1.5 is about types, whereas I was
> asking about engine adapter templates.
Actually I think regarding your question, [rand.req.adapt] is the
right place to start first. And the answer is much easier if you use a
formal language for requirements. I'm referring to the concept
language from draft N2914 here.
> My corrected question is essentially the same:
>
> In section 26.5.4 Random number engine adaptor class templates [rand.adapt], nothing is said
> about whether the random engine adapter template must accept, as a type template parameter,
> *all* random number engine types as in section 26.5.1.4.
Correct, [rand.adapt] describes library-provided type families where
any feasible instantiations satisfy the engine adaptor requirements
from [rand.req.adapt].
> If a class template will only compile for a subset of all of the random number engine types,
> can it still satisfy the requirements of 26.5.4?
Without precise concepts, 26.5.4 is hard to speculate upon. But let my
try to start with a more formal definition of these requirements, then
let's we were we end.
> On Thursday, March 22, 2012 2:23:45 PM UTC-4, Daniel Kr gler wrote:
>>
>>
>> In my opinion you are talking about two issues:
>>
>> 1) The most simple one is your last question: The answer is trivial:
>> Every requirement set can be refined to an arbitrary degree of
>> constraints. Given that fundamental property of refinements of concepts
>> there is no point that you can define your own random number engine
>> adaptor that accepts only a restricted set of engines (and the
>> restrictions can be defined by your-self).
>
>
> I think I've now clarified that (1) is not an issue?
After having completed this response I agree that (1) is not an issue here.
>> 2) Nonetheless I think that you are asking an interesting question in
>> regard to what the library specification describes. It is a fact that
>> all specialized library-defined engine adaptors do refer to evaluating
>> the expression e() given its engine(s) e in some way. This is to be
>> expected given the "interface" of general random number engines. From
>> the perspective of the standard, there does not exist any engine concept
>> which provides another way of reading the generated values of it's state
>> except from a function call expression without parameters. ...
>
>
> Yes, this is the whole point: I am assuming that an engine could provide some other
> way of reading generated values, in addition to those required by the standard, and
> still satisfy the requirements of 26.5.1.4 (yes?)
I don't see how this should work: The litmus test is: Does your engine
adaptor accept *any* engine (with or without reverse function)? If
not, it cannot satisfy the requirements from [rand.req.adapt]. But
hold on...
> I will describe some specifics on the engine adapter template that led to my question.
> I have my own concept of a "reversible random number engine", refining 26.5.1.4.
Here is the right point to start: You define your own refined random
number engine. This is proper way to make things clear.
For clarification purposes I'm presenting the corresponding concept
definitions from N2914 that should match with the textual description
of the current spec (as part of this discussion I'm ignoring the
aspects of "auto concepts" and others, I'm only concerned about
matching a concept here). We have
concept UniformRandomNumberGenerator<typename G> {
typename result_type;
requires UnsignedIntegralLike<result_type> && IntegralType<result_type>;
result_type operator()(G&);
//...
}
concept RandomNumberEngine<typename E> : UniformRandomNumberGenerator<E> {
//...
}
> In addition to the requirements of a random number engine, a
> reversible random number engine
>
> provides a method reverse() which generates random numbers in reverse order of operator()().
OK, so you say "in addition", which means that you provide the
required operator(), right? In this case, "reversible random number
engine" is a proper *refinement* of the "random number engine"
requirements. I translate this to
concept ReversibleRandomNumberEngine<typename E> : RandomNumberEngine<E> {
result_type G::reverse();
}
Fine for me so far.
> Then I have an adapter template called reverse_adapter:
>
> template<typename Engine, ...> class reverse_adapter { ... };
>
> In general it will only compile if Engine is a reversible random number engine (i.e. has a reverse()
> method). (It should be obvious what the adapter does.)
>
>
> My question is whether reverse_adapter can satisfy the requirements of the standard,
> since it will not accept all Engine types?
It depends on the requirements ;-) But lets start formally: From a
standard perspective we have
concept RandomNumberEngineAdaptor<typename A, typename B0, typename...
Bi> : RandomNumberEngine<A> {
requires RandomNumberEngine<B0> && RandomNumberEngine<Bi>...;
//...
}
as the requirement set for random number engine adaptors. Let's
compare with that one in the following.
> My interpretation of the standard is yes,
> since there is no explicit requirement to accept all Engine types. However, I know others
> who have interpreted this section of the standard differently.
I agree that this is hard to conclude from the existing wording,
because this textual definition is far less precise than a formal
language. In concept language I would translate your type as
satisfying a refined requirement set described by
concept ReversibleRandomNumberEngineAdaptor<typename A, typename B0,
typename... Bi> :
RandomNumberEngineAdaptor<A, B0, Bi...>
{
requires ReversibleRandomNumberEngine<B0> &&
ReversibleRandomNumberEngine<Bi>...;
}
Note that this definition has two sides:
a) It demonstrates that your reverse_adaptor can be considered as
modelling some ReversibleRandomNumberEngineAdaptor requirement set,
which indirectly means that it also models RandomNumberEngineAdaptor
which means it models some specific random number engine adaptor that
is described by [rand.req.adapt].
b) But it also shows that reverse_adaptor imposes stronger
requirements on the random number engine, so *not all* random number
engines are accepted. In this sense your adaptor should not be
considered as equivalent to the templates of [rand.adapt], which
accept *any* random number engine.
I'm emphasizing (b) here, because it acts like a kind of
contravariance rule here in contrast to the usual covariance rule of
return types of overrides of derived classes.
Let me close with a more practical example: The std::reverse_iterator
adaptor template can also be considered as an iterator adaptor which
imposes stronger requirements on the template parameter compared to
the std::move_iterator adaptor template. This approach is absolutely
feasible, but you should not forget to mention the additional
requirements on the engine argument.
HTH & Greetings from Bremen,
Daniel Kr gler
--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: MiloRambaldi<james.hirschorn@gmail.com>
Date: Mon, 2 Apr 2012 15:16:45 -0700 (PDT)
Raw View
Thank you very much for your helpful explanations.
It is great that there is a formalized conceptual language. Up to my understanding of this concepts language you have correctly interpreted what I meant by ReverseRandomNumberEngine and ReversibleRandomNumberEngineAdapter.
However, I'm not certain I fully understand yet. I have made a few statements below to check my understanding, and would be grateful if you could point out any errors in these statements.
On Saturday, March 24, 2012 10:26:49 PM UTC-4, Daniel Kr gler wrote:
...
>
> I don't see how this should work: The litmus test is: Does your engine
> adaptor accept *any* engine (with or without reverse function)? If
> not, it cannot satisfy the requirements from [rand.req.adapt]. But
> hold on...
>
...
>
> OK, so you say "in addition", which means that you provide the
> required operator(), right? In this case, "reversible random number
> engine" is a proper *refinement* of the "random number engine"
> requirements. I translate this to
>
> concept ReversibleRandomNumberEngine<typename E> : RandomNumberEngine<E> {
> result_type G::reverse();
> }
>
> Fine for me so far.
>
> > Then I have an adapter template called reverse_adapter:
> >
> > template<typename Engine, ...> class reverse_adapter { ... };
> >
> > In general it will only compile if Engine is a reversible random number engine (i.e. has a reverse()
> > method). (It should be obvious what the adapter does.)
>
> >
> >
> > My question is whether reverse_adapter can satisfy the requirements of the standard,
> > since it will not accept all Engine types?
>
>
> It depends on the requirements ;-) But lets start formally: From a
> standard perspective we have
>
> concept RandomNumberEngineAdaptor<typename A, typename B0, typename...
> Bi> : RandomNumberEngine<A> {
> requires RandomNumberEngine<B0> && RandomNumberEngine<Bi>...;
> //...
> }
>
> as the requirement set for random number engine adaptors. Let's
> compare with that one in the following.
>
> > My interpretation of the standard is yes,
> > since there is no explicit requirement to accept all Engine types. However, I know others
> > who have interpreted this section of the standard differently.
>
>
> I agree that this is hard to conclude from the existing wording,
> because this textual definition is far less precise than a formal
> language. In concept language I would translate your type as
> satisfying a refined requirement set described by
>
> concept ReversibleRandomNumberEngineAdaptor<typename A, typename B0,
> typename... Bi> :
> RandomNumberEngineAdaptor<A, B0, Bi...>
> {
> requires ReversibleRandomNumberEngine<B0> &&
> ReversibleRandomNumberEngine<Bi>...;
> }
>
> Note that this definition has two sides:
>
> a) It demonstrates that your reverse_adaptor can be considered as
> modelling some ReversibleRandomNumberEngineAdaptor requirement set,
> which indirectly means that it also models RandomNumberEngineAdaptor
> which means it models some specific random number engine adaptor that
> is described by [rand.req.adapt].
According to my best understanding of what you have said:
(1) reverse_adapter does *not* model RandomNumberEngineAdapter, and therefore does not satisfy section [rand.req.adapt] of the standard.
(2) reverse_adapter does model the concept ReverseRandomNumberEngineAdapter, which indirectly "models" RandomNumberEngineAdpater by deriving from it and imposing further requirements on the Bi's. (Though I am a bit confused by what you mean by "it models some specific random number engine adaptor that is described by [rand.req.adapt]".)
And most importantly:
(3) Even though reverse_adapter does not satisfy the requirements of [rand.req.adapt], this is not a "defect" in the adapter, and just means that the additional requirement must be documented.
>
> b) But it also shows that reverse_adaptor imposes stronger
> requirements on the random number engine, so *not all* random number
> engines are accepted. In this sense your adaptor should not be
> considered as equivalent to the templates of [rand.adapt], which
> accept *any* random number engine.
>
> I'm emphasizing (b) here, because it acts like a kind of
> contravariance rule here in contrast to the usual covariance rule of
> return types of overrides of derived classes.
>
> Let me close with a more practical example: The std::reverse_iterator
> adaptor template can also be considered as an iterator adaptor which
> imposes stronger requirements on the template parameter compared to
> the std::move_iterator adaptor template. This approach is absolutely
> feasible, but you should not forget to mention the additional
> requirements on the engine argument.
--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]
Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Tue, 3 Apr 2012 23:20:09 -0700 (PDT)
Raw View
On 2012-04-03 00:16, MiloRambaldi wrote:
>>
>> > My interpretation of the standard is yes,
>> > since there is no explicit requirement to accept all Engine types. However, I know others
>> > who have interpreted this section of the standard differently.
>>
>> I agree that this is hard to conclude from the existing wording,
This was supposed to mean: The actual interpretation is hard to
conclude from the existing wording.
>> because this textual definition is far less precise than a formal
>> language. In concept language I would translate your type as
>> satisfying a refined requirement set described by
>>
>> concept ReversibleRandomNumberEngineAdaptor<typename A, typename B0,
>> typename... Bi> :
>> RandomNumberEngineAdaptor<A, B0, Bi...>
>> {
>> requires ReversibleRandomNumberEngine<B0> &&
>> ReversibleRandomNumberEngine<Bi>...;
>> }
>>
>> Note that this definition has two sides:
>>
>> a) It demonstrates that your reverse_adaptor can be considered as
>> modelling some ReversibleRandomNumberEngineAdaptor requirement set,
>> which indirectly means that it also models RandomNumberEngineAdaptor
>> which means it models some specific random number engine adaptor that
>> is described by [rand.req.adapt].
>
>
> According to my best understanding of what you have said:
>
> (1) reverse_adapter does *not* model RandomNumberEngineAdapter, and therefore does not satisfy section [rand.req.adapt] of the standard.
You got this conclusion wrong. What I was trying to say is that your
type (family) *does* satisfy the RandomNumberEngineAdapter
requirements (Note that it is less refined than
ReversibleRandomNumberEngineAdaptor) but it *also* imposes additional
requirements. In this regard it is not a *pure* refinement.
This is no fundamental defect, but it allows to argue that not all
Engines can be used as feasible arguments. My picture using
std::reverse_iterator (which also may not accept all iterators as
template arguments) was trying to demonstrate that your example is not
unique. You only have to keep in mind that reverse_adapter is some
special constrained RandomNumberEngineAdapter.
> (2) reverse_adapter does model the concept ReverseRandomNumberEngineAdapter, which indirectly "models" RandomNumberEngineAdpater by deriving from it
Yes, except that concepts don't derive from other concepts, they can
only refine other concepts. The syntax just looks like inheritance.
> and imposing further requirements on the Bi's.
Correct.
> (Though I am a bit confused by what you mean by "it models some specific random number engine adaptor that is described by [rand.req.adapt]".)
This should basically say the same as I described in my reply to (1)
above: "It models some *specific* [..]" was intended to emphasize the
fact that it imposes additional constraints upon the more general
requirement set from [rand.req.adapt].
> And most importantly:
>
> (3) Even though reverse_adapter does not satisfy the requirements of [rand.req.adapt],
> this is not a "defect" in the adapter, and just means that the additional requirement must be documented.
Exactly.
HTH & Greetings from Bremen,
Daniel Kr gler
--
[ comp.std.c++ is moderated. To submit articles, try posting with your ]
[ newsreader. If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html ]