Boost logo

Boost Users :

From: Zach Laine (whatwasthataddress_at_[hidden])
Date: 2019-10-30 15:46:36


On Wed, Oct 30, 2019 at 6:55 AM Richard Damon via Boost-users <
boost-users_at_[hidden]> wrote:

> On 10/30/19 1:03 AM, Zach Laine via Boost-users wrote:
> >
> > Yes, you got me. I was speaking loosely, and referred to a template
> > as if it were a type. What I should have added was that a template's
> > single responsibility should be to stamp out types that all model the
> > same concept. A policy-based template has a hard time doing that. A
> > policy-based template that stamps out strings with different
> > invariants does not do that at all.
> >
> But all the various templates may well express a base concept even if
> some of the invariants change between different template parameters. The
> example of Unicode normalization, or memory allocator seem like perfect
> examples of this. If an operation needs a particular normalization rule,
> it specializes its parameter on that one case, otherwise it leaves it as
> a template parameter.
>
> To me, the basic invariant of a string is that it is a sequence of code
> units that describe a textual object. Often the details of that encoding
> are unimportant, it might be ASCII, it might be in some old code page,
> it might be in UTF-8, it might be in UCS-4, and for the various Unicode
> variations, there are different normalization rules to handle that a
> given 'character' (aka Glyph) might be expressed in different ways, but
> the routine largely doesn't care. When it does care, it can force the
> string into that variant (or refuse some other variants), but the
> purpose of templates is to condense duplicate code into a single piece
> of code that only needs to be written once.
>

You're mixing kinds of abstractions here. There is the genericity you find
in a function that takes a generic parameter, and that's the kind of use
based on concept you're talking about here. About that you're 100% correct:

template<foo_concept T>
auto foo(T const & x); // <-- feel free to pass any type here that models
foo_concept

Part of why the above code works is that foo() only uses x in certain ways,
and anything that meets the syntactic requirements is well-formed. If
foo_concept describes a sequence container, I only care about the common
interface of a sequence container. Specifically, I cannot use
vector::reserve(), and don't really care that it exists.

Where that breaks down is when you have not a function template that uses
certain aspects of a type, but a class template that represents a set of
types. That case is different:

foo_template<T> foo; // <-- feel free to use the entire API

If the API is different for various values of T, such as it would be for a
text template that instantiates as string-like or rope-like (because those
have significantly different interfaces), that implies to me that I should
have two names in play -- one for the string version and one for the rope
version. Otherwise, the result is super confusing for someone reading or
writing code using the unified name.

Zach



Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net