std::function construction vs assignment

58 views
Skip to first unread message

barry....@gmail.com

unread,
Sep 13, 2016, 9:44:20 AM9/13/16
to ISO C++ Standard - Discussion
The constructor template for std::function is specified as:

template<class F> function(F f);

where:

Otherwise, *this targets a copy of f initialized with std::move(f).

On the other hand, the copy assignment operator template for std::function is specified as:

template<class F> function& operator=(F&& f);

 where:

Effects: As if by: function(std::forward<F>(f)).swap(*this);

Should the constructor template take a forwarding reference instead of just a value? The operator takes by forward reference  as a result of http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1288, but that one didn't mention the constructor. 

Daniel Krügler

unread,
Sep 14, 2016, 1:33:10 PM9/14/16
to std-dis...@isocpp.org
2016-09-13 15:44 GMT+02:00 <barry....@gmail.com>:
> The constructor template for std::function is specified as:
>
> template<class F> function(F f);
>
> where:
>
>> Otherwise, *this targets a copy of f initialized with std::move(f).
>
> On the other hand, the copy assignment operator template for std::function
> is specified as:
>
> template<class F> function& operator=(F&& f);
>
> where:
>
>> Effects: As if by: function(std::forward<F>(f)).swap(*this);
>
> Should the constructor template take a forwarding reference instead of just
> a value?

That sounds plausible, yes.

>The operator takes by forward reference as a result of
> http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#1288, but that
> one didn't mention the constructor.

It didn't mention the constructor, because the key argumentation was:

"This assignment operator can be called such that F is an rvalue-reference e.g.

func.operator=<F&&>(f);

There are two issues with this. "

But exactly that form of explicit argument provision isn't possible
for a constructor.

- Daniel

barry....@gmail.com

unread,
Sep 14, 2016, 3:50:34 PM9/14/16
to ISO C++ Standard - Discussion
> Should the constructor template take a forwarding reference instead of just
> a value?

That sounds plausible, yes.

Can I propose we make that a [minor and easy to fix] LWG defect? The forwarding-reference constructor saves a move over the by-value constructor, and it's more consistent with assignment operator. 

Is there a reason to specifically prefer a by-value constructor over a forwarding-reference one?

Daniel Krügler

unread,
Sep 14, 2016, 3:57:54 PM9/14/16
to std-dis...@isocpp.org
2016-09-14 21:50 GMT+02:00 <barry....@gmail.com>:
>> > Should the constructor template take a forwarding reference instead of
>> > just
>> > a value?
>>
>> That sounds plausible, yes.
>
> Can I propose we make that a [minor and easy to fix] LWG defect? The
> forwarding-reference constructor saves a move over the by-value constructor,
> and it's more consistent with assignment operator.

Makes sense to me, please submit it to the lwgchair address.

> Is there a reason to specifically prefer a by-value constructor over a
> forwarding-reference one?

The only reason I can imagine is that you need carefully check the
existing specification for unwanted side-effects of that change. One
example of this is that now F could be a reference type and
cv-qualified, so presumably you need some wording massaging taking
advantage of std::decay_t (see wording for std::any as a similar
example).

Thanks,

- Daniel

T. C.

unread,
Sep 14, 2016, 4:42:36 PM9/14/16
to ISO C++ Standard - Discussion


On Wednesday, September 14, 2016 at 3:57:54 PM UTC-4, Daniel Krügler wrote:

> Is there a reason to specifically prefer a by-value constructor over a
> forwarding-reference one?

The only reason I can imagine is that you need carefully check the
existing specification for unwanted side-effects of that change. One
example of this is that now F could be a reference type and
cv-qualified, so presumably you need some wording massaging taking
advantage of std::decay_t (see wording for std::any as a similar
example).

Thanks,

- Daniel

Also a constraint so that it doesn't hijack the copy constructor. You don't need that when it's by-value because core ensures that you never get a "copy" constructor taking its argument by value.

Tim
Reply all
Reply to author
Forward
0 new messages