Boost logo

Boost :

From: David Abrahams (dave_at_[hidden])
Date: 2006-06-19 12:39:09


Andy,

I'm impressed with the thought and effort you're putting into this.
Keep it up.

"Andy Little" <andy_at_[hidden]> writes:

> Is there not a universal syntax for C++ concept documentation to
> which everyone should conform or in which every construct can be
> expressed?

Every construct? Probably not. I can't prove that the existing
idioms cover everything, including constraints I've never seen.
However, they cover most things and you're not doing anything so
exotic that it shouldn't fit.

FWIW, once we have concept support in the language we will be using
pseudosignatures rather than valid expressions to express syntactic
constraints, so we can expect that to change. In the meantime,
though, the things that can be expressed using established conventions
should be so expressed.

>>> PQS uses both forms of Concept. Is there any means or language
>>> convention to distinguish the two forms?
>>
>> There are not really two different forms AFAICT.
>
> OK. I have difficulties with that because it seems to contradict
> your remark about **in the context of MPL**. MPL is exclusively a
> compile time library. The TMP in PQS borrows heavily form MPL.

All that means is that when you're reading the docs for an MPL
metafunction and you see foo<...>::type and have a "Type" column
header, you know you're dealing with a type member and not a value
member, and you don't need further disambiguation. That's ALL it
means. So if you want to avoid ambiguity there, say your
"compile-time" templates are MPL metafunctions. Well, you'd better
make sure they _are_ metafunctions first :)

> If I implement more planned features of the PQS library, I will need runtime and
> compile time versions of many Concepts. An example of this is (lets call it )
> DimensionA Concept which in the TMP book Dimensional Analysis example is
> modelled by the mpl::vector of dimensional exponents.
>
> In PQS it is also desirable to have a runtime version, this time modelled (say
> for simplicity) by something encapsulating a std::vector<int>. This would be a
> model of (lets call it) DimensionB.
>
> The two Concepts need to be distinguished. I'm not sure if there is a naming
> convention in use to distinguish the two.

Static vs. Dynamic.

> I thought of a Meta prefix for the DimensionA category
> (MetaDimension) and none for the latter (just Dimension).

It's not really meta.

> OTOH I thought of a namespace prefix meta::Dimension, but I think
> that would be unconventional. I read you werent happy about use of
> the word meta but it seems to have the right connotations to me

Not me. Meta implies that it will be operating on itself.

> FWIW, Const might do but I think the difference between these two is
> not well described by that.

static :)

>>> My current intention is to put the compile-time requirement Concepts
>>> under a separate section from the runtime requirement Concepts.
>>
>> Almost every concept you write that has runtime requirements also has
>> compile-time requirements, so I don't know if this division makes much
>> sense. But I'm much more concerned with the contents of the concept
>> descriptions than the order in which they're presented.
>
> I have put my latest effort at getting one PQS Concept
> (AbstractQuantity) right, into the Boost vault in Physical
> Quantities Units/ AbstractQuantity.html. http://tinyurl.com/7m5l8
>
> BTW I am aware the formatting is poor, and external links go nowhere but
> currently I am just trying to get the syntax right (or more accurately the right
> ballpark)

This concerns me:

   A model of AbstractQuantity is also either a model of NamedQuantity
   or of AnonymousQuantity. Types modelling NamedQuantity are usually
   created by the programmer, while types modelling AnonymousQuantity
   usually arise as temporary results of calculations, somewhat
   analogous to L-values and R-values).

AFAIK there's no precedent for a concept that sometimes refines one
concept and sometimes refines another, but always refines one of them,
and I think it will make things very difficult if you continue that way.

What is an Entity Relationship Diagram? Do you possibly mean a
diagram of concept refinement? If so, why not just say that?

I don't know what I'm supposed to see below "Notation," but it's
completely unfamilar to me. Is there supposed to be a table
somewhere?

It looks like:

  Notation

  In the AbstractQuantity Synopsis and functions tables Lhs and Rhs
  and Q are types that are models of AbstractQuantity and R is type
  that is a model of Rational.

  AbstractQuantity Synopsis

  a::divides,Rhs>;
  concept AbstractQuantity{};
  Requirements:
  meta::binary_operation<Lhs,meta::plus,Rhs>;
  meta::binary_operation<Lhs,meta::minus,Rhs>;
  meta::binary_operation<Lhs,meta::times,Rhs>;
  meta::binary_operation<Lhs,met
  meta::binary_operation<Q,meta::pow,R>;
  meta::dimension<Q>;
  meta::dimensionally_equivalent<Lhs,Rhs>;
  meta::is_dimensionless<Q>;
  meta::is_named_quantity<Q>;
  meta::is_anonymous_quantity<Q>;
  meta::is_same_quantity<Lhs,Rhs>;

  Notes

  Math on the associated Dimension of an AbstractQuantity works
  logarithmically, so addition and subtraction of the
  DimensionalExponents of a Dimension transform to no-ops ( the types
  of dimension<Lhs> and dimension<Rhs> are required to be
  dimensionally equivalent), multiplication to addition, division to
  subtraction and raising to a power to multiplication.

  Functions
  meta::binary_operation<Lhs,meta::plus,Rhs>
  </
  Description: Returns the type resulting from addition of 2 types modelling AbstractQuantity
  Expression:
  meta::binary_operation<Lhs,meta::plus,Rhs>::type
  Requires:
  dimensionally-equivalent<Lhs,Rhs> models True
  Returns:
  A model of AbstractQuantity Q where:

       dimensionally-equivalent<Q,Lhs > models True.

  And
       dimensionally-equivalent<Q,Rhs > models True.

  And (
  If
       same_quantity<Lhs,Rhs> models True
  Then
       same_quantity<Q,Lhs> models True
  Else
       is_anonymous_quantity<Q> models True.)

> FWIW in rewriting PQS library, I am now aiming to make the Concepts
> wide enough so that the examples using mpl::vectors in TMP book
> should work though they will need specialisations(overloads?) of the
> metafunctions in the PQS Requirements to work of course.

Sorry, not "of course," because you lost me.
Make concepts wide? You mean the tables?
Some examples from the TMP book should work with PQS? How?

> I guess this may have been what you were getting at in your review
> of PQS? IOW Some parts of the PQS library provide models of the
> Concepts, while other parts (metafunctions act in terms of Concepts)
> so can be applied to other models than the ones supplied.

Still lost.

> ------------
>
> The following is some questions I am trying to answer. Maybe they just reflect
> my current confusion over this whole subject. Anyway I thought they might be
> interesting to see my struggles as a newcomer to this subject. I am currently
> looking over examples and may find answers to some questions there.
>
> Questions resulting from trying to do the AbstractQuantity Concepts in the above
> mentioned AbstractQuantity.html
>
> Associated metafunctions
>
> 1) Should I use the term return type with metafunctions?
>
> e.g typedef f<T>::type result;
>
> I see the above in terms of a function f returning a type, which IMO is quite
> acceptable in the TMP domain. I would then have a Returns clause in the
> specification describing the return type of f. It seems to be used this way in
> MPL docs anyway.

I would do whatever the MPL reference manual does, as long as you make
it clear that the template is a metafunction.

> 2) Overloaded metafunctions.
>
> I have overloaded? specialised?

Specialized of course. Where did you ever see the term "overload"
applied to class templates? I understand that there's an analogy
there, but it's not an exact one, and my whole point was that you
shouldn't be inventing new naming conventions and notation in a domain
where you don't yet feel very comfortable.

> the metafunctions in a similar way to runtime functions are
> overloaded. An obvious example is the pqs::meta::binary_operation
> metafunction in the sample. This is meant to be entirely equivalent
> to runtime operator functions such as operator +. ( std::string +
> std:: string , int + int , IOW its just an operator)
>
> Now however I need to express the overload of the Concept
> arguments.

Sorry, I'm lost again. Why not revert to standard terminology? What
is a "concept argument?" Concepts are neither types nor templates
(unless you mean concept checking classes, which I again highly
recommend you write), so I don't see how they can either be or have
arguments.

> The way it seems to be done is to put in some Preamble
> (Sometimes called Notation?) that in the following, Lhs and Rhs are
> models of Concept X.

That's a familiar idiom before a concept requirements table, yes.

> The problem is that is remote from the per item description:
>
> binary_operation<Lhs,Op,Rhs>
>
> IMO It would make more sense to say e.g.
>
> binary_operation<AbstractQuantity Lhs,Op,AbstractQuantity Rhs>

Maybe it would (in fact something like that will be available with the
language support for concepts), but as I said this is not the time to
invent new notations. Get comfortable with the existing conventions
first.

If you wanted to look at ConceptGCC and actually write conforming
new-style concepts, I'd find it hard to fault you... but I don't think
that would be as useful to your readers, and for you I think that
might be overreaching at this stage.

> 3) Why no BooleanConstant Concept?
>
> boost::typetraits uses true_type_or_false_type. MPL uses IntegralConstant
> Concept. Should there be a (say) BooleanConstant Concept?

Why? Do you have some code that needs an IntegralConstant whose
values can only be true or false (I.e. the code won't work as expected
if the value is 2)? If so, you might consider a BooleanConstant
concept. But you might also consider just making the code work right
when the value is 2.

> (Also IMO then there should be a True Concept and a False concept)

The existence of concepts is driven by the requirements of generic
code. If you don't have code that requires a type's conformance to
these properties, don't make a concept. Also, some concepts don't
need to be separately named. For example, you can say "a
nonzero-valued MPL IntegralConstant" or "a true-valued MPL
IntegralConstant" when you mean the True concept. Whether it's
worthwhile to make a separate True concept might depend on how often
you find yourself needing it in your documentation.

> This would be more generic and could apply to MPL and type_traits
> return types.

More generic how?

> 4)Am I right in saying there is a fair amount of variability in Concept
> documentation?.

Sorry, it's too subjective a question for me to answer definitively.
I'd guess that most concept documentation exists at Boost. There is
some poor concept documentation out there, and also some in here.

> It strikes me that there could be a more abstract syntax to describe
> Concepts. Many times I want to say for example:
>
> T Is True , meaning that in code where true_ is some model of True then one
> (among several) ways for a type t to model this Concept is
>
> struct c : true_ {};

I usually say a "true-valued IntegralConstant" for that.

You don't need to invent a more abstract syntax to describe that True
concept. The standard requirements table and other notations will do
just fine:

     True Concept

     Refines: IntegralConstant

     Requirements:
     
        In the table below, T is a model of True.

        +--------------------+--------------------+
        |Expression |Semantics |
        +====================+====================+
        |T::value |nonzero |
        +--------------------+--------------------+
        

-- 
Dave Abrahams
Boost Consulting
www.boost-consulting.com

Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk