Boost logo

Boost Users :

From: Jonathan Turkanis (technews_at_[hidden])
Date: 2005-08-25 12:00:03


Daniel Krügler wrote:
> Jonathan Turkanis wrote:
>> Daniel Krügler wrote:
>>
>>> Jonathan Turkanis wrote:
>>>
>>>> Daniel Krügler wrote:
>>
>>
>>>>> 2) The function template
>>>>>
>>>>> template <typename IntType>
>>>>> IntType lcm(IntType n, IntType m);
>>>>>
>>>>> should be defined as
>>>>>
>>>>> template <typename IntType>
>>>>> IntType lcm(IntType n, boost::call_traits<IntType>::param_type m);
>>>>>
>>>>> which makes sense in this case because m is not modified
>>>>> internally (in contrast to n)
>>>>
>>>>
>>>> I think lcm should be symmetrical.
>>>
>>> 1) Wow, not so much of details of reasonings, please ;-))
>>
>>
>> Because the semantics are symmetrical. The above asymmetry wouldn't
>> be acceptable for max or +, would it?
>
> No, because they would use
>
> template <typename IntType>
> IntType lcm(const IntTyp& n, const IntTyp& m);
>
> as shown in my previous posting.

My point was: even if the assymetrical version were more efficient, the
interface would be unacceptable.

>> How much performance improvement do you expect, and in what cases?
>
> I expect performance differences in case of (most probably dynamically
> growing) arbitrary-precision integer types, as described in my
> original posting. As explained in detail by referencing the boost
> docs it is an explicit intention of the current design.

I guess I missed your reference to the docs.

> Following my reasoning we currently have one unnecessary copy of one
> the 2nd argument in lcm and both of my proposals do not have this
> deficiency. I think we don't have to discuss about cases where the
> arguments are native integral types, but we have to consider something
> like std::integer, see
>
> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1744.pdf

Okay. Pass by value should be okay for built-in integral types, then.

>>> 2) OK, the request of symmetry can lead to several conclusions:
>>>
>>> If we argue that the interface should not reflect the
>>> implementation, the most reasonable signature would be something
>>> like
>>>
>>> template <typename IntType>
>>> IntType lcm(const IntTyp& n, const IntTyp& m);
>>>
>>> (We cannot use the optimal version
>>>
>>> template <typename IntType>
>>> IntType lcm(boost::call_traits<IntType>::param_type n,
>>> boost::call_traits<IntType>::param_type m);
>>>
>>> because that would prevent argument deduction)
>>>
>>> Otherway around we could argue, that we want to use advantages of
>>> a special copy-optimization technique. This is an
>>> implementation-driven
>>> interface, but there are cases, where proposers (I am not one) have
>>> argued that the advantages outweight its disadvantages.
>>
>>
>> Okay, what are you arguing, then?
>
> Interuption of the sentences does not make sense here. I think the
> answer follows from the complete paragraph and I do answer below.

I put my comment between two of your paragraphs. You're the one who interrupted
the sentences ;-)

>>> If I try to compare these to approaches not too strongly
>>> subjectively (its impossible, I know, but I'll try ;-))), than I
>>> would say, that an implementation-driven interface should be only
>>> used where necessary, but not otherwise. This lead to my proposal
>>> to use call-by-value only for the first, not for the second
>>> argument of lcm.
>>
>>
>>> I don't understand, **why** you think, that the interface
>>> must/should be
>>> symmetric:
>>>
>>> 1) Thinking not implementation-driven, than
>>>
>>> template <typename IntType>
>>> IntType lcm(const IntTyp& n, const IntTyp& m);
>>>
>>> would be right thing for general IntTypes (see std::max/min
>>> interface). I would agree to that proposal
>>
>>
>> Are you saying this is always better than pass by value, or just
>> sometimes?
>
> As **one** general solution this would be best, yes. Currently there
> is only one general solution, so I am discussing about that.
>
> Call by value would be probably somewhat better for native integral
> types (This is the reason for call_traits). This fact was the reason
> for my original proposal of the asymmetric version.
>
> Thinking in **one** general solution, I propose either the asymmetric
> version or the version using reference arguments as both arguments,
> whatever you like. I only wanted to show a direction which to my
> opinion is better than the current state, I don't say that my proposal
> is the best of the set of all possible solutions.
>
> If one prefers finer granulation one could of course replace the
> single general solution by SFINAE-overloading techniques to handle
> cheap-copyable types by others and if any one would prefer that, I
> would applaud to that.

Why do we need SFINAE? I can just define overloads for built-in intergal types,
and a templated version that uses const references.

>>> 2) Thinking implementation-driven, than
>>>
>>> template <typename IntType>
>>> IntType lcm(IntType n, boost::call_traits<IntType>::param_type m);
>>>
>>> must be acceptable and **even more reasonable** than the currently
>>> existing
>>>
>>> template <typename IntType>
>>> IntType lcm(IntType n, boost::call_traits<IntType>::param_type m);
>>>
>>> interface.
>>
>>
>> They look the same to me.
>
> Sorry, I made a mistake here. My (asymmetric) proposal is:
>
> template <typename IntType>
> IntType lcm(IntType n, boost::call_traits<IntType>::param_type m);
>
> and the current state is:
>
> template <typename IntType>
> IntType lcm(IntType n, IntType m);

Okay.

> Daniel

Jonathan


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