Boost logo

Boost :

Subject: Re: [boost] Formal review for QVM
From: Emil Dotchevski (emil_at_[hidden])
Date: 2015-12-14 19:07:05


On Mon, Dec 14, 2015 at 3:16 PM, Agustín K-ballo Bergé <
kaballo86_at_[hidden]> wrote:

> On 12/14/2015 7:57 PM, Emil Dotchevski wrote:
>
>> On Mon, Dec 14, 2015 at 1:12 PM, Agustín K-ballo Bergé <
>> kaballo86_at_[hidden]> wrote:
>>
>> On 12/14/2015 5:53 PM, Emil Dotchevski wrote:
>>>
>>> On Mon, Dec 14, 2015 at 4:46 AM, Agustín K-ballo Bergé <
>>>>
>>>> if the compiler says there is an error here because `normalized` needs a
>>>
>>>> default constructor, I'm gonna start suspecting something wrong is going
>>>>> on
>>>>> with the library. This is what I would naively expect `normalized` to
>>>>> be
>>>>> doing:
>>>>>
>>>>> template <typename Vec>
>>>>> Vec normalized(Vec v) {
>>>>> return v /= length(v);
>>>>> }
>>>>>
>>>>>
>>>> It can't be implemented that way because the type of the argument might
>>>> not
>>>> be copyable.
>>>>
>>>>
>>> Does this mean that the library explicitly supports movable-only types?
>>> That's somewhat unexpected, given that the library requires all type
>>> information necessary for embedded storage, but it's not a bad thing. It
>>> would be good to add this information to the reference documentation.
>>>
>>
>> QVM is neutral wrt move semantics but views are non-copyable and
>> non-movable because copy or move semantics would require a temporary
>> object, which QVM views are carefully designed to avoid. You can assign to
>> a view and it will convert to any compatible type, but you can't copy or
>> move it. That's why you can chain views up with no overhead: any operation
>> on a view or multiple chained views works with the original object, no
>> other objects are created.
>>
>
> Views are special, that has already been established. My question was not
> in regard of views, whose case I said is unsurprising. My question was with
> respect to this simple guy requiring the presence of a default constructor:
>
> myvec3 n = normalized(myvec3(1, 2, 3));
>
> Why does this guy require a default constructor? Now you said the library
> cannot call a constructor other than the default one, which is not the
> case. So I wonder if you had experimented with this particular case, which
> does not conceptually require a default constructor, and for which the
> library is already calling another constructor, a copy/move constructor
> given the simple fact that it is being returned from a function.
>
> Why does this guy require a default constructor? I understand now that it
> doesn't, you simply don't want to handle this case any different than you
> already do views. There's nothing wrong with that.

I'm not sure if we're on the same page. I'll try again. :)

If you have

struct myvec3 { .... };

then if you go:

myvec3 v1 = ....;
myvec3 v2=normalized(v1);

It is indeed puzzling why would that need a default constructor. But
consider this code:

struct mymat3 { .... };

mymat3 m = ....;
myvec3 v=normalized(col<1>(m)); //Take column 1 as vector

In this case col<1> returns a reference to m, which is passed by reference
to normalized. The use of col<1> created no temporary, but the flip side is
that the reference it returns is of type that (by design) is neither
copyable or movable.

If instead you did:

myvec3 v=normalized(col<1>(transp(m))); //Transpose, then take column 1 as
vector

transp returns a reference to m, which col<1> takes by reference and
returns by reference, which is then passed by reference to normalized(), so
again, no temporary is created in this sequence of calls.

But in the end, normalized must return an object -- and it can't use a copy
constructor (different types). And since I've never encountered a vector
type without a default constructor, it seemed reasonable to not worry too
much about requiring it.

Emil


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