[std-interval] PODs and parameter passing

first.i.last at comcast.net first.i.last at comcast.net
Fri Apr 7 02:39:06 PDT 2006


 -------------- Original message ----------------------
From: Gabriel Dos Reis <gdr at integrable-solutions.net>
> first.i.last at comcast.net writes:
> 
> [...]
> 
> | > | > 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? 
> 
> Because whether the operations in question are permitted or not would
> depend on the compiler; I don't see any compelling reason for that
> sort of non-portability.

It is only non-portable if it is not detectable at compile time.

> 
> | I hope offsetof() is not going to be used much on intervals. 
> 
> It is a reasonable hope; others have other reasonable expectations
> too.  The question is not whether it would be used "too much", but
> whether it should be permitted at all.  I can see arguments both
> ways; but none that convinces me of the non-portability you suggest.
> 
> | There
> | would be little point in scrounging around inside an interval unless
> | you are trying to cause (yourself) some trouble. 
> 
> That is your expectation; others expect to "serialize" things, using
> offsetof among other things -- and we do have an open issue with
> std::complex for example, from various point of view.

Serialization suggests interval::operator<<() and interval::operator>>() rather than offsetof(), but the (non-)existence of those methods is a hugely contentious issue.  In fact serialization of the mental model "double interval[2]' could be handled by a user with upper() and lower().  Deserialization is just use of an appropriate constructor.  I have very little sympathy for users who insist on below-API access to objects.

Does anyone reading this list believe that using offsetof() on intervals is a healthy practice?  If so, to what end?

> 
> | Initialization of an interval is almost certainly going to require a
> | ctor due to the problem of compiler mangling of literal constants,
> 
> I'm sorry; I don't see the connection.  Could you elaborate?
> 
> | so for purposes of initialization intervals aren't going to behave
> | like PODs even if they are PODs. 
> 
> I don't see why.

If we allow classic static init then the compiler will be translating the text of literal values into binary.  If that translation occurs without directed rounding it will produce degenerate intervals that astonish the user and are in reality containment failures.  Consider this:

    static interval const tenths[] = 
    { { 0.0, 0.0 }
    , { 0.1, 0.1 } // oops
    , { 0.2, 0.2 } // oops
    , { 0.3, 0.3 } // oops
    , { 0.4, 0.4 } // oops
    , { 0.5, 0.5 }
    , { 0.6, 0.6 } // oops
    , { 0.7, 0.7 } // oops
    , { 0.8, 0.8 } // oops
    , { 0.9, 0.9 } // oops
    };

The array will contain the correct values only if the translation of the two members of each element is done with opposing directed rounding of the individual results.  So we might be force to use only dynamic initialization such as:

    static interval const tenths[] = 
    { interval( "[0.0]" }  // only used for consistency of notation
    { interval( "[0.1]" }
    { interval( "[0.2]" }
    { interval( "[0.3]" }
    { interval( "[0.4]" }
    { interval( "[0.5]" }  // only used for consistency of notation
    { interval( "[0.6]" }
    { interval( "[0.7]" }
    { interval( "[0.8]" }
    { interval( "[0.9]" }
    };

The above produces two degenerate intervals and eight non-degenerate intervals, will not astonish the user, and has no containment failures (assuming interval::interval( char const * ) works properly).

Thus PODness is not everywhere advantageous.

Is the distinction clear from the above example?

> | Can you think of any other fine details (other than things like
> | binary IO) that might influence the preference for PODs over "real"
> | objects? 
> 
> It all depends on the degree of non-PODness; there are ABIs out there
> on popular platforms that make optimization decisions based on degree
> of PODness.

Let's see if we can mutate a classic into something useful:

    Intervals should be as POD as possible and no PODer.
          -- apologies to Albert?

-- Lee Winter


More information about the Std-interval mailing list