C++ guys hate static_if?

Dmitry Olshansky dmitry.olsh at gmail.com
Thu Mar 14 12:30:36 PDT 2013


14-Mar-2013 22:55, H. S. Teoh пишет:
> On Thu, Mar 14, 2013 at 10:20:04PM +0400, Dmitry Olshansky wrote:
>> 14-Mar-2013 22:13, H. S. Teoh пишет:
>>> On Thu, Mar 14, 2013 at 06:09:26PM +0100, Andrej Mitrovic wrote:
>>>> On 3/14/13, bearophile <bearophileHUGS at lycos.com> wrote:
>>>>> This is an invalid argument. You can say the same thing for many
>>>>> (most?) tests done by the compiler. Unit tests can't be sure to
>>>>> verify all code paths inside a function or template.
>>>>
>>>> No, it must do exactly that. If you have so many paths that you
>>>> can't reasonably test all paths then your template or function is
>>>> too complicated to begin with. The benefit here of D over C++ is
>>>> that unit testing is cheap and doesn't require external libraries.
>>> [...]
>>>
>>> I think you're missing the point. The point is that concepts allow
>>> the compiler to deduce template correctness *without* instantiating
>>> it with every possible combination of types.
>>>
>>> Right now, we *don't* have concepts, and therefore the only way to
>>> ensure template correctness is to iterate over the exponential number
>>> of combinations of template arguments.
>>
>> And if you create a library tool to try out all sensible
>> combinations would that work for this use case of concepts?
>>
>> In essence you transform concept to some specification and feed it
>> into a CTFE-able generatopr function. Then take the code out and
>> apply mixin it put into a unittest.
>>
>> Sounds easy (if only DMD doesn't run out of memory in the process).
> [...]
>
> It's certainly possible, I think. Is it worth pursuing? Maybe.

It is as this won't require arguing with Walter, Andrei et al. and the 
other wopuld either use it or not but you both ways you'd have hard data.

> Here's a
> first crack at it:
>
> We'd need some way of listing (or generating a list of) all
> representative template arguments, say for example, a listing that
> includes input range, forward range, bidirectional range, etc.. Then we
> need a way to generically generate non-trivial instances of these ranges
> (otherwise the unittest could only cover trivial instances, like empty
> input range, empty forward range, etc., so the template being tested
> will not be verified for non-empty ranges!). The result then will be
> used to instantiate the template and run it through a battery of tests.
>
> Of course, the ranges themselves have arguments, so you'd need some kind
> of listing of representative types: char, int, float, string, etc., and
> have a way of generating non-trivial instances of each of these types,
> then use them to instantiate the range with. Maybe for each type also
> test it for const(T), immutable(T), etc..
>
> Then you'd have to cover nested ranges, so you'd need a way to specify
> how deep you want to go (e.g., a recent forward range bug of using =
> instead of .save will only manifest itself if you had a nested range of
> forward ranges -- you couldn't catch that just by running through
> non-nested ranges).
>
> As you can see, this quickly explodes in exponential number of
> combinations. So ultimately, maybe we still have to resort to
> hand-picked "representative" types.

No - just use some language (DSL!) for the specification instead of 
generating type-strings. Basically exactly the same thing you'd put into 
a concept if it was langauge feature.

You'd have a spec written in this language per each concept: input range 
of type X, an infinite range of type Y, an output range for E, etc. Spec 
states unit tests (and not only) for any type satisfying a concept. The 
concept (spec) itself is parametrize on types and/or other concepts.

Then your tests are kind of monte carlo - pick random (large number) X 
of full spectrum (infinite on types, but finite on meta-types) of type 
combinations that this template supports and run the generated unit 
tests for these.

That pick (following the spec) should cover all of the rules in the 
concept. The types themselves should include dummies generated based on 
the spec and some real world stuff (predefined).

>
> But we can do better than the current ad-hoc scheme of writing unittests
> for whatever combination just occurred to the code writer (which usually
> misses a lot of corner cases). We should have a std.unittest module that
> contains lists of all numeric types (byte, int, long, float, double,
> real, etc.) with their respective non-trivial instances, as well as
> representative range types: {arrays, struct ranges, class ranges} x
> {input, forward, bidirection, ...}, along with non-trivial instances of
> them. Then provide some generic testing functions that iterate over each
> of these lists, that user-written unittests can call to instantiate and
> test their templates with.
>

Exactly. But I'd call for more high-callibre module as in std.testing.spec.

> There can also be a way of adding custom types to the lists, that the
> generic functions can pick up and include in their combinations to test.

> But the important thing is to collect these type lists in a single
> place, so that we can, for example, test std.algorithm functions that
> expect input ranges with *all* ranges in the input range list, and be
> reasonably certain that if it all passes, the chances for any more bugs
> are very slim. (Otherwise, std.algorithm.joiner may have good coverage
> but std.algorithm.cartesianProduct may have poor coverage, and there's
> lots of missed reuse opportunities for the test ranges used by the
> unittests.)
>

That would be a huge step forward but it's like collecting sets of 
strings and use their concatenation to define a required set of strings. 
Instead you could use a formal grammar and define much broader kinds of 
sets with less "lines"/"rules" (like even regular grammar does).


-- 
Dmitry Olshansky


More information about the Digitalmars-d mailing list