1

As a follow-up to Can tr1::function swallow return values?, how can one work around the limitation that tr1::function cannot swallow return values?

This should work in the specific case of swallowing the return value of a callable object taking no arguments:

template<typename FuncT>
struct swallow_return_t
{
  explicit swallow_return_t(FuncT i_Func):m_Func(i_Func){}
  void operator()(){ m_Func(); }
  FuncT m_Func;
};

template<typename FuncT>
swallow_return_t<FuncT>
swallow_return(FuncT f)
{
  return swallow_return_t<FuncT>(f);
}

Then use like:

int Foo();
std::tr1::function<void()> Bar = swallow_return(Foo);

I assume variadic templates and perfect forwarding would permit generalization of this technique to arbitrary parameter lists. Is there a better way?

Community
  • 1
  • 1
Chris
  • 103
  • 3

1 Answers1

0

The following works for me in GCC 4.6.1:

#include <functional>

int foo() { return 5; }
int goo(double, char) { return 5; }

int main()
{
  std::function<void()> f = foo;
  std::function<void(float, int)> g = goo;
  (void)f();
  (void)g(1.0f, 'a');
}

Here's a wrapper using lambdas, but it's not automagic yet

template <typename T, typename ...Args>
struct strip_return
{
  static inline std::function<void(Args...)> make_function(std::function<T(Args...)> f)
  {
    return [&f](Args... args) -> void { f(args...); };
  }
};

int main()
{
  auto q = strip_return<int>::make_function(std::bind(foo));
  q();
}

Forget the middle part. OK, since std::function is type-erasing, it's hard to get at the underlying types. However, if you go for the function reference directly, you can avoid these problems entirely:

template <typename T, typename ...Args>
static inline std::function<void(Args...)> make_direct(T (&f)(Args...))
{
  return [&f](Args... args) -> void { f(args...); };
}

int main()
{
  auto p = make_direct(foo);
  q();
}
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • 1
    The question seems to be specifically about MSVC if you check out the linked question. It doesn't help to say that no workaround is needed with GCC... – UncleBens Jul 11 '11 at 17:02
  • It was suggested in a comment in the linked question that this behavior is not permitted in the new standard. – Chris Jul 11 '11 at 17:04
  • @UncleB: Whoops, sorry. We should tag the question as "MSVC". @Chris: Really? If that's so then we should write a wrapper. One minute... – Kerrek SB Jul 11 '11 at 17:11
  • It's nice that the lambda function eliminates the need for defining a separate functor. Should strip_return be taking and the lambda be capturing f by reference? I thought these things usually operated on values and used ref() when reference semantics were needed. – Chris Jul 11 '11 at 17:34
  • Where "these things" means function adapters/wrappers/etc. – Chris Jul 11 '11 at 17:35
  • @Chris: OK, I added a version for direct function references which doesn't use `bind` and doesn't require template parameters. – Kerrek SB Jul 11 '11 at 17:52
  • I was afraid a general solution would be just as complicated as `function`. – Chris Jul 11 '11 at 18:25