[contract] auto_..._error regression tests fail on C++1z

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
Hello all,

I asked this question on compl.c++ list as well, given this is more of
a general C++1z question than a Boost question. However, this is
making some Boost.Contract regression tests fail on C++1z compilers so
I wanted to ask it here as well hoping to get some info more
quickly...

Following code prevents copies outside its friend function f:

    // File: 05.cpp

    struct x {
        x() {}
    private:
        x(x const&) {}
        x& operator=(x const&) { return *this; }

        friend x f();
    };

    x f() { return x(); }

    int main() {
        auto xx = f();
        return 0;
    }

Correctly it does not compile up to C++1y because main cannot access
the copy operations:

    $ clang++ -std=c++1y 05.cpp
    05.cpp:14:15: error: calling a private constructor of class 'x'
        auto xx = f();
                  ^
    05.cpp:5:5: note: declared private here
        x(x const&) {}
        ^
    1 error generated.

However, it compiles on C++1z?!

    $ clang++ -std=c++1z 05.cpp
    # Not compiler errors?!

Why... what changed in C++1z that makes the above compile? How can I
prevent copying x outside its friend function f in C++1z?

Thanks,
--Lorenzo

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
> Why... what changed in C++1z that makes the above compile? How can I
> prevent copying x outside its friend function f in C++1z?

C++ 17 guarantees copy elision in the strong sense.

Note it still can't be copied, but it can be initialised now. So disable
non-friend construction to fix.

Niall

--
ned Productions Limited Consulting
http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
AMDG

On 09/28/2017 04:58 PM, Lorenzo Caminiti via Boost wrote:

> <snip>
>
> Correctly it does not compile up to C++1y because main cannot access
> the copy operations:
>
>     $ clang++ -std=c++1y 05.cpp
>     05.cpp:14:15: error: calling a private constructor of class 'x'
>         auto xx = f();
>                   ^
>     05.cpp:5:5: note: declared private here
>         x(x const&) {}
>         ^
>     1 error generated.
>
> However, it compiles on C++1z?!
>
>     $ clang++ -std=c++1z 05.cpp
>     # Not compiler errors?!
>
> Why... what changed in C++1z that makes the above compile? How can I
> prevent copying x outside its friend function f in C++1z?
>

  This code no longer makes a copy, and
does not require the copy constructor.

In Christ,
Steven Watanabe


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On Thu, Sep 28, 2017 at 4:05 PM, Niall Douglas via Boost
<[hidden email]> wrote:
>> Why... what changed in C++1z that makes the above compile? How can I
>> prevent copying x outside its friend function f in C++1z?
>
> C++ 17 guarantees copy elision in the strong sense.
>
> Note it still can't be copied, but it can be initialised now. So disable
> non-friend construction to fix.

I see. However, making the constructor private still does not make the
compilation fail. The following code compiles fine on clang++
-std=c++1z ...

struct x {
private:
    x() {}
    x(x const&) {}
    x& operator=(x const&) { return *this; }

    friend x f();
};

x f() { return x(); }

int main() {
    auto xx = f();
    return 0;
}

Is there any way to make that `auto xx = f()` in main fail at compile
time in C++1z?

Thanks,
--Lorenzo

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
2017-09-29 4:29 GMT+02:00 Lorenzo Caminiti via Boost <[hidden email]>
:

> On Thu, Sep 28, 2017 at 4:05 PM, Niall Douglas via Boost
> <[hidden email]> wrote:
> >> Why... what changed in C++1z that makes the above compile? How can I
> >> prevent copying x outside its friend function f in C++1z?
> >
> > C++ 17 guarantees copy elision in the strong sense.
> >
> > Note it still can't be copied, but it can be initialised now. So disable
> > non-friend construction to fix.
>
> I see. However, making the constructor private still does not make the
> compilation fail. The following code compiles fine on clang++
> -std=c++1z ...
>
> struct x {
> private:
>     x() {}
>     x(x const&) {}
>     x& operator=(x const&) { return *this; }
>
>     friend x f();
> };
>
> x f() { return x(); }
>
> int main() {
>     auto xx = f();
>     return 0;
> }
>
> Is there any way to make that `auto xx = f()` in main fail at compile
> time in C++1z?
>

But why do you want this program to fail to compile?

Regards,
&rzej;

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
On Tue, Oct 3, 2017 at 11:45 PM, Andrzej Krzemienski via Boost
<[hidden email]> wrote:
> 2017-09-29 4:29 GMT+02:00 Lorenzo Caminiti via Boost <[hidden email]>
>>
>> Is there any way to make that `auto xx = f()` in main fail at compile
>> time in C++1z?
>>
>
> But why do you want this program to fail to compile?

The library requires to explicitly use `boost::contract::check c =
boost::contract::function()`. Using `auto c =
boost::contract::function()` or `boost::contract::function()` (without
assigning it to anything) will generate a run-time error. This is well
documented. On non C++1z compilers, the library will also give a
compile-time error if `auto c = boost::contract::function()` is used
by mistake (but this no longer fails compilation on C++1z so you are
left with just the run-time error in that case on C++1z).

In summary, this is just to catch a misuse of the API at compile-time
instead of run-time... this is well documented so it shouldn't be a
real issue in practice.

P.S. I'm surprised that I can no longer write a type in C++1z that
will fail compilation when used via its copy operations... I wonder if
that is an unintended consequence of the zero-copy optimization
guarantee that C++1z has. Sure no copies should be made at run-time,
but I should still get a compile-time error if I try to use a copy
operation on a type that does allow copy, even when these copies are
guaranteed to be optimized away in C++11z.

Thanks.
--Lorenzo

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
On 10/4/2017 12:48 PM, Lorenzo Caminiti via Boost wrote:

> On Tue, Oct 3, 2017 at 11:45 PM, Andrzej Krzemienski via Boost
> <[hidden email]> wrote:
>> 2017-09-29 4:29 GMT+02:00 Lorenzo Caminiti via Boost <[hidden email]>
>>>
>>> Is there any way to make that `auto xx = f()` in main fail at compile
>>> time in C++1z?
>>>
>>
>> But why do you want this program to fail to compile?
>
> The library requires to explicitly use `boost::contract::check c =
> boost::contract::function()`. Using `auto c =
> boost::contract::function()` or `boost::contract::function()` (without
> assigning it to anything) will generate a run-time error. This is well
> documented. On non C++1z compilers, the library will also give a
> compile-time error if `auto c = boost::contract::function()` is used
> by mistake (but this no longer fails compilation on C++1z so you are
> left with just the run-time error in that case on C++1z).
>
> In summary, this is just to catch a misuse of the API at compile-time
> instead of run-time... this is well documented so it shouldn't be a
> real issue in practice.
>
> P.S. I'm surprised that I can no longer write a type in C++1z that
> will fail compilation when used via its copy operations... I wonder if
> that is an unintended consequence of the zero-copy optimization
> guarantee that C++1z has. Sure no copies should be made at run-time,
> but I should still get a compile-time error if I try to use a copy
> operation on a type that does allow copy, even when these copies are
> guaranteed to be optimized away in C++11z.

I think you mistyped and should have written:

"but I should still get a compile-time error if I try to use a copy
operation on a type that does not allow copy, even when these copies are
guaranteed to be optimized away in C++11z."

I agree with that sentiment also, so I am equally surprised that a
compile-time error does not occur. I would be very interested in the
part of the C++17 standard which explains why I do not get a
compile-time error in the example case where f() is a private function.

>
> Thanks.
> --Lorenzo


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: [contract] auto_..._error regression tests fail on C++1z

Boost - Dev mailing list
In reply to this post by Boost - Dev mailing list
On Wed, 2017-10-04 at 09:48 -0700, Lorenzo Caminiti via Boost wrote:

> On Tue, Oct 3, 2017 at 11:45 PM, Andrzej Krzemienski via Boost
> <[hidden email]> wrote:
> >
> > 2017-09-29 4:29 GMT+02:00 Lorenzo Caminiti via Boost <[hidden email]..or
> > g>
> > >
> > >
> > > Is there any way to make that `auto xx = f()` in main fail at compile
> > > time in C++1z?
> > >
> > But why do you want this program to fail to compile?
> The library requires to explicitly use `boost::contract::check c =
> boost::contract::function()`. Using `auto c =
> boost::contract::function()` or `boost::contract::function()` (without
> assigning it to anything) will generate a run-time error. This is well
> documented. On non C++1z compilers, the library will also give a
> compile-time error if `auto c = boost::contract::function()` is used
> by mistake (but this no longer fails compilation on C++1z so you are
> left with just the run-time error in that case on C++1z).
>
> In summary, this is just to catch a misuse of the API at compile-time
> instead of run-time... this is well documented so it shouldn't be a
> real issue in practice.
>
> P.S. I'm surprised that I can no longer write a type in C++1z that
> will fail compilation when used via its copy operations... I wonder if
> that is an unintended consequence of the zero-copy optimization
> guarantee that C++1z has. Sure no copies should be made at run-time,
> but I should still get a compile-time error if I try to use a copy
> operation on a type that does allow copy, even when these copies are
> guaranteed to be optimized away in C++11z.

Yes, this is the semantic difference with guaranteed copy elision. So now
`NonMoveable x = NonMoveable{5}` is semantically equivalent to `NonMoveable
x{5}`. This is done by tweaking the value categories, so `NonMoveable{5}` no
longer produces a temporary object, but rather `NonMoveable{5}`(ie a prvalue)
performs initialization at the location of `NonMoveable x`(ie a glvalue).
There are exceptions where a temporary object will always be created(from
P0135):

* when a prvalue is bound to a reference
* when member access is performed on a class prvalue
* when array subscripting is performed on an array prvalue
* when an array prvalue is decayed to a pointer
* when a derived-to-base conversion is performed on a class prvalue
* when a prvalue is used as a discarded value expression

I dont know if any of those exceptions can help in your case. I ran into the
same problem with the Fit library, and was unable to find a workaround. 

It would be nice if compiler could provided the ability to force a temporary
object to always be created from a function.

Paul

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost