Title
std::function should support all callable types
Status
c++11
Section
[func.wrap.func.con]
Submitter
Daniel Krügler

Created on 2009-12-19.00:00:00 last changed 162 months ago

Messages

Date: 2010-11-23.13:22:14

Proposed resolution:

Change [func.wrap.func.con]/10+11 as indicated:

template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);

...

10 Postconditions: !*this if any of the following hold:

  • f is a NULL function pointer.
  • f is a NULL pointer to member function pointer.
  • F is an instance of the function class template, and !f

11 Otherwise, *this targets a copy of f or, initialized with std::move(f) if f is not a pointer to member function, and targets a copy of mem_fn(f) if f is a pointer to member function. [Note: implementations are encouraged to avoid the use of dynamically allocated memory for small function objects, for example, where f's target is an object holding only a pointer or reference to an object and a member function pointer. — end note]

Date: 2010-11-23.13:22:14

[ Adopted at 2010-11 Batavia ]

Date: 2010-10-21.19:06:53

[ Post-Rapperswil: ]

Moved to Tentatively Ready after 5 positive votes on c++std-lib.

Date: 2011-05-03.22:13:16

Some parts of the specification of std::function is unnecessarily restricted to a subset of all callable types (as defined in [func.def]/3), even though the intent clearly is to be usable for all of them as described in [func.wrap.func]/1. This argument becomes strengthened by the fact that current C++0x-compatible compilers work fine with them:

#include <functional>
#include <iostream>

struct A
{
  int foo(int i) const {return i+1;}
};

struct B
{
  int mem;
};

int main()
{
  std::function<int(const A&, int)> f(&A::foo);
  A a;
  std::cout << f(a, 1) << '\n';
  std::cout << f.target_type().name() << '\n';
  typedef int (A::* target_t)(int) const;
  target_t* p = f.target<target_t>();
  std::cout << (p != 0) << '\n';
  std::function<int(B&)> f2(&B::mem);
  B b = { 42 };
  std::cout << f2(b) << '\n';
  std::cout << f2.target_type().name() << '\n';
  typedef int (B::* target2_t);
  target2_t* p2 = f2.target<target2_t>();
  std::cout << (p2 != 0) << '\n';
}

The problematic passages are [func.wrap.func.con]/10:

template<class F> function(F f);
template <class F, class A> function(allocator_arg_t, const A& a, F f);

...

10 Postconditions: !*this if any of the following hold:

  • f is a NULL function pointer.
  • f is a NULL member function pointer.
  • F is an instance of the function class template, and !f

because it does not consider pointer to data member and all constraints based on function objects which like [func.wrap.func]/2 or [func.wrap.func.targ]/3. The latter two will be resolved by the proposed resolution of 870 and are therefore not handled here.

History
Date User Action Args
2011-08-23 20:07:26adminsetstatus: wp -> c++11
2010-11-23 13:22:14adminsetmessages: + msg5400
2010-11-14 13:10:57adminsetstatus: voting -> wp
2010-11-08 14:14:39adminsetstatus: ready -> voting
2010-10-21 19:06:53adminsetmessages: + msg4767
2010-10-21 19:06:53adminsetstatus: new -> ready
2010-10-21 18:28:33adminsetmessages: + msg1476
2009-12-19 00:00:00admincreate