Workaround to allow tr1::function to swallow return values
Asked Answered
P

1

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?

Plasma answered 11/7, 2011 at 16:45 Comment(0)
M
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();
}
Menswear answered 11/7, 2011 at 17:0 Comment(7)
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...Leralerch
It was suggested in a comment in the linked question that this behavior is not permitted in the new standard.Plasma
@UncleB: Whoops, sorry. We should tag the question as "MSVC". @Chris: Really? If that's so then we should write a wrapper. One minute...Menswear
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.Plasma
Where "these things" means function adapters/wrappers/etc.Plasma
@Chris: OK, I added a version for direct function references which doesn't use bind and doesn't require template parameters.Menswear
I was afraid a general solution would be just as complicated as function.Plasma

© 2022 - 2024 — McMap. All rights reserved.