From: Brian McNamara (lorgon_at_[hidden])
Date: 2003-10-06 13:54:37
On Mon, Oct 06, 2003 at 10:55:43AM -0700, Mat Marcus wrote:
> So here are a few principles with some thin justification. I don't
> claim that these are perfect or complete. Maybe a bit of discussion
> will refine them.
> Specify libraries using concepts instead of, say, using abstract base
> classes where possible and appropriate. In such cases the following
> principles might apply.
> Avoid making member functions part of the public API where
> possible. Whether or not something is a member function is strictly an
> implementation detail. Offer your libs functionality as a collection
> of free functions and/or function templates.
> Avoid making member data part of your public API. Prefer the get()
I pretty much agree with all this.
> Avoid nested types. But also avoid traits classes in an attempt to
> reify metafunctions. Prefer free metafunctions. We don't need more
> fat, closed traits classes anymore then we need more fat closed
My point is that a so-called "traits class" need not close off future
design possibilities. The way I envision a traits class (or traits
namespace), is that it simply is a group of ("free") metafunctions
which are all related by virtue of being members of the same concept.
That is, for each concept (SomeConcept), there should be some type of
entity (SomeConcept_traits) which has as its members all of the "free
metafunctions" associated with that concept.
As a result, when Joe-Programmer wants a utility to discover the
value_type of a container (for any container--even an array), he can
look in one place--inside "container_traits"--for a (free) value_type
(unary) metafunction, rather than having to look all over the library
trying to find the same "container_value_type" metafunction. (I am
aware that I am "dramatizing" the issue a bit.)
> Of course questions remain. One particular area that needs some more
> work is the question of modules/namespaces. I would argue that
> reification into classes/objects is undesirable, but some kind of
> packaging is needed. This can get rather complicated in the
> presence of ADL and the potential unboundedness function
> templates. SFINAE/enable_if may be of some help and perhaps techniques
> like Brian suggests could be of some use for compile time packaging,
> but there remain questions of overhead. I'd be interested to hear what
> thoughts others may have had on this subject.
A few other points:
Since some concepts (like Container) are closed (the standard says what
they are; we cannot add new constraints to this concept), it does no
harm to package the Container traits metafunctions in a (closed) class.
Once a concept has been defined and come into standard use in practice,
it is (in any reasonable practical sense) already a "closed" entity
--regardless of whether the C++ code representing this entity is
That last sentence is important enough that it bears repeating:
Once a concept has been defined and come into standard use in
practice, it is (in any reasonable practical sense) already a
I don't see how ADL is an issue. The way I see things, everything uses
I have been using the term "concept reification" to mean something to
me, and I fear it means something else to other people. I'm not sure
how to resolve this potential-communication-problem easily.
The issue of overhead-due-to-nesting should not be considered. If we
were really worried about this, we would not already be doing all of
our programming in namespaces like boost::mpl::iterator::detail (or
whatever). (There are potentially some other overheads which ought to
be considered, but I want to single this particular one out as a
-- -Brian McNamara (lorgon_at_[hidden])
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk