Preventing implicit conversion from std::function<T()> to std::function<T const &()>?

83 views
Skip to first unread message

stephan.bergm...@googlemail.com

unread,
Apr 18, 2016, 5:30:45 AM4/18/16
to ISO C++ Standard - Discussion
It seems to be quite common that people get bitten by the (non-explicit)

  template<typename R, typename... ArgTypes> template<F> std::function<R(ArgTypes...)>::function(F)

constructor allowing to implicitly convert some std::function<T()> to a std::function<T const &()>. Especially when calling the latter does not generate warnings with many popular compilers/standard library implementations. See e.g. <http://stackoverflow.com/questions/23284971/does-stdfunction-allow-an-implicit-cast-from-reference-to-copy-in-its-return-t> and <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70692> "No warning when std::function<const int&(...)> binds a reference to a temporary" (spawned from comment 1 to <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64329#c1> "Crash when returning reference from lambda with deduced type").

AFAICS, there is no useful way in which a std::function<T()> dressed as a std::function<T const &()> can actually be used. Calling it will always result in a dangling reference to a temporary that has already been destroyed. Wouldn't it be better to change the Standard to exclude this constructor when it would introduce a reference in the return type? I don't find this discussed on this list or in the defect reports yet.

Brian Bi

unread,
Oct 31, 2016, 8:14:53 PM10/31/16
to std-dis...@isocpp.org
Bump


I think we can make this a compile error if the std::function<R(A...)> constructor is disabled when:
  • R is a reference to cv1 T, and
  • the callable object returns a prvalue of type cv2 U, and
  • U is the same as T, or is a class type derived from T.

Is there not a DR for this already?


--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.



--
Brian Bi

David Krauss

unread,
Nov 16, 2016, 2:50:57 AM11/16/16
to std-dis...@isocpp.org
On 2016–11–01, at 8:14 AM, Brian Bi <bbi...@gmail.com> wrote:

Bump


I think we can make this a compile error if the std::function<R(A...)> constructor is disabled when:
  • R is a reference to cv1 T, and
  • the callable object returns a prvalue of type cv2 U, and
  • U is the same as T, or is a class type derived from T.

Reference binding can also include pointer conversions, with an lvalue-to-rvalue step. So function<int *()> or even function<int *&()> converts to function<int const *const &()> defectively.

It might be generally useful to have a type trait is_reference_compatible, to reveal whether a given reference initialization binds a temporary.

David Krauss

unread,
Nov 17, 2016, 3:32:42 AM11/17/16
to std-dis...@isocpp.org
I’ve implemented a fix in my library implementation.

The std::function<R(A...)> constructor is disabled when R is a reference to cv1 T and

  • the callable object returns a prvalue and its type is not a class type reference-unrelated to T, or
  • the callable object returns a glvalue and its type is neither cv2 T nor a class type.

In other words, the erasure delegate permits

  • only user-defined conversions when returning a prvalue by reference, and
  • only user-defined and derived-to-base conversions when returning a glvalue by reference.

Any possible issues with this?


On 2016–11–01, at 8:14 AM, Brian Bi <bbi...@gmail.com> wrote:

Brian Bi

unread,
Nov 18, 2016, 3:04:21 PM11/18/16
to std-dis...@isocpp.org
David, do you want to take a stab at proposed wording?

http://cplusplus.github.io/LWG/lwg-active.html#2813

--

---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-discussion+unsubscribe@isocpp.org.
To post to this group, send email to std-dis...@isocpp.org.
Visit this group at https://groups.google.com/a/isocpp.org/group/std-discussion/.



--
Brian Bi
Reply all
Reply to author
Forward
0 new messages