[std-interval] PODs and parameter passing

first.i.last at comcast.net first.i.last at comcast.net
Thu Apr 6 18:34:47 PDT 2006


 -------------- Original message ----------------------
From: Gabriel Dos Reis <gdr at integrable-solutions.net>
> first.i.last at comcast.net writes:
> 
> [...]
> 
> | > | > Please note that our proposed interval type is meant to be a POD (plain
> | > | > old data) type and as such has no copy constructor nor destructor.
> | > | 
> | > | Is it your plan that the proposal include the POD-only requirement?  I 
> would 
> | > | suggest that it is an obvious possibility that yeilds good performence 
> | > | improvements, but how important is it to get fat intervals quickly?
> | > | 
> | > | I would must prefer not to see such a requirement in the standard.
> | > 
> | > The proposal would need to be precise about whether internal<T> is a
> | > POD or not; that is unavoidable.
> | 
> | Why?
> 
> because if the proposal is accepted, it is going to be part of a much
> larger context.  They are some operations on can do on types depending
> on whether they are PODs or not, like offsetof, initializations and
> other fine details.  The standard needs to say whether such operations
> are permitted or not.

OK, I did not ask a sufficiently precise question.  Why is "implementation defined" unacceptable?  I.e., why does PODness have to be a constant for all implementations?

I hope offsetof() is not going to be used much on intervals.  There would be little point in scrounging around inside an interval unless you are trying to cause (yourself) some trouble.

Initialization of an interval is almost certainly going to require a ctor due to the problem of compiler mangling of literal constants, so for purposes of initialization intervals aren't going to behave like PODs even if they are PODs.

Can you think of any other fine details (other than things like binary IO) that might influence the preference for PODs over "real" objects?

> 
> [...]
> 
> | In this regard I consider things like specific requirements of
> | PODness to be a kind of fine print that should be minimized. 
> 
> probably; but in the context we are talking about, you have to
> specify.  You can't do without it -- and we learnt it the hard way.

OK I accept your judgement that a specification is necessary.  That leaves the issue of whether it can be delegated to the implementation.  If it can be then its worth discussing whether it should be.
 
> 
> [...]
> 
> | > | > The issue was the mechanism for passing the representation, not the
> | > | > logical opacity of the type.
> | > | 
> | > | The issue is the atomicity of the type.  Atomicity often implies effective 
> | > | opacity.  Opacity always implies atomicity.
> | > 
> | > Yet, at the end of the day the proposal needs to spell out the
> | > mechanism for passing the representation.  At the moment, I don't see
> | > how the committee would buy a proposal that is very vague about such
> | > issue.  Past experience with vagueness in that area has been a fertile
> | > source of programmer confusion, and defect reports (that the committee
> | > had to deal with).
> | 
> | Is an abstract type for parameters vague?
> 
> In C++, there is the notion of "abstract class" but I doubt that is
> what you were refering to.  One has to be more specific than general
> terms; this is not a language independent specification.

Abstractions hide implementation details.  The previous suggestion (yours?) of interval::param_type would hide either "interval const &" or "interval" type definitions.  That would certainly be usefu, but  dependent types are problematic.  The only variation I'm suggesting is to make that parameter type independent of the interval template type.

> 
> | > [...]
> | > 
> | > | > Message: 7
> | > | > Date: 05 Apr 2006 15:37:20 +0200
> | > | > From: Gabriel Dos Reis <gdr at integrable-solutions.net>
> | > | > Subject: Re: [std-interval] passing by value vs reference
> | > | > To: For discussions concerning the C++ standardization of intervals
> | > | > 	<std-interval at compgeom.poly.edu>
> | > | > Message-ID: <m3d5fwcfe7.fsf at uniton.integrable-solutions.net>
> | > | > Content-Type: text/plain; charset=iso-8859-1
> | > | > 
> | 
> | > | > If done that way, in the typical cases, the "T" would then appear in
> | > | > non-deducible context. 
> | > | 
> | > | It need not be a dependent type.  It could easily by a parallel set of 
> templates.
> | > 
> | > More specifically?
> | 
> | ----- interval.h -----
> |     template< T > struct Interval    { ... };
> |     template< T > struct IntervalArg { ... };
> 
> That is half of it; the other half is how are they used concretely in
> specifying function parameters?  That is the most interesting bits.
> Please don't be afraid to be concrete, otherwise I fear we would not
> communicate effectively: the issue at hand is too concrete.
> 
> | Such an abstraction would require each implementor to document the
> | calling convention actually used so that interfacing with other
> | languages was possible, but implementations already have to document
> | all kinds of calling convention properties of which parameter
> | passing is only one. 
> 
> How is IntervalArg<T> is different from IntervalArg<T>?  What do they
> contain? 

OK, I'll bite.  For this discussion assume Interval<T> is the same as the existing proposal.  If Interval<T> were not a template, say intervalf, interval, and intervalld, and intervalq in C99-style naming,  then we would use intervalf_arg_t, interval_arg_t, intervalld_arg_t, and intervalq_arg_t as corresponding argument types.  They would be implementation defined.  Everywhere that one wanted to pass in interval argument one would use the corresponding *arg_t to maintain platform optimization agility.

But Interval is going to be a template.  It is tempting to want to derive the argument type, hre named IntervalArg from the value type Interval.  But templates ahve weaknesses, one of which inhibits that derivation.

So I'm suggesting an independent template.  In crudest terms it would be something like this :
    
namespace pbr {

    template< typename T >
    struct IntervalArg { typedef T const & _t; };

    struct IntervalArg<float>
    { typedef Interval<float> const & _t; };

    struct IntervalArg<double>
    { typedef Interval<double> const & _t; };

    ... ditto for other fp types

} // pbr

namespace pbv {

    template< typename T >
    struct IntervalArg { typedef T const & _t; };

    struct IntervalArg<float>
    { typedef Interval<float> _t; };

    struct IntervalArg<double>
    { typedef Interval<double> _t; };

    ... ditto for other fp types

} // pbv

In use it would be a bit ugly:

    using namespace pbv; // or pbr
    template< typename T >
    Interval<T> agile_func( IntervalArg<T>::_t arg1 ) { ... }

A subtlety that may not be immediately apparent is that the purpose of the unspecialized template is to address contexts in which a template parameter T represents an interval type, whose base type is not specific.  Thus:

    template< typename T /* in truth Interval<U> */ >
    struct userdefined {
        ...
        T interval_func( IntervalArg<T>::_t arg );
        ...
    }; // userdefined

A more complex implementation would eliminate the unsightly ::_t along the lines of a proxy type.  It would rely upon the compiler to optimize away all of the bookkeepping:

namespace pbr {

    template < typename T >
    struct IntervalArg {  // for discussion purposes only
        IntervalArg( Interval<T> arg )
        : ref_( val )
        {}
        operator Interval<T> () const
        { return ref_; }
    private:
        Interval<T> const & ref_;
    };

} // pbr

namespace pbv { // all of this optimizes away

    template < typename T >
    struct IntervalArg {  // for discussion purposes only
        IntervalArg( Interval<T> arg )
        : val_( arg )
        {}
        operator Interval<T> () const
        { return val_; }
    private:
        Interval<T> val_;
    };

} // pbv

Usage is then straightforward:

    using namespace pbv; // or pbr
    template< typename T >
    Interval<T> agile_func( IntervalArg<T> arg1 ) { ... }

Lest any reader misunferstand, I am _not_ proposing that both pbr and pbv be available.  I only used the namespaces to separate the alternative implementations for the purposes of clarity within this discussion.

> 
> | Does the interval standard need to be specific about who cleans
> | arguments off of the stack?
> 
> Once we know what IntervalArg<T> and Interval<T> contain and do, we
> can get to that question.

I was being facetious.  I suppose that's an error in judgement when one is indulging in language laywering.  ;-)

Stack cleaning conventions don't belong in the standard IMHO.

> 
> [...]
> 
> | > [ As I mentioned earlier, I'm not sure template aliases help in this
> | > case. ]
> | 
> | I don't understand the term template alias.  Coud you describe one?
> 
> A "template alias" is an alias for a family of types
> 
>    http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2003/n1489.pdf

Nope.  I'm not going there!  Not now, and probably not ever.

Thanks for the info.

-- Lee Winter


More information about the Std-interval mailing list