parameter pack expansion not working in lambda

吃可爱长大的小学妹 提交于 2019-12-08 06:31:27
#include <iostream>

namespace test
{
  template<typename F, typename... Args>
  void callback_dispatcher(F call, Args&& ...args )
  {   
    std::cout << "callback_dispatcher>" << __PRETTY_FUNCTION__ << "enter <<< " << std::endl;                                                 
    auto invoke_me = [=]()mutable{
      call(std::move(args)...);
    };  
    invoke_me();
  }   
}

int main()
{
  std::cout << "Main entered..." << std::endl;


  test::callback_dispatcher(
    [](int a)
    {
      std::cout << "void(int) lambda dispatched with a = " << a << std::endl;
    },
    5
  );

  std::cout << "Main exited..." << std::endl;
}

The above slight change compiles in gcc 4.9 and up, but not in gcc 4.8.5.

It also compiles in modern versions of clang.

Update your compiler, or don't use c++11 features that your compiler doesn't support.

You may be able to pack your args into a tuple, then unpack them in the body of the function.

  template<typename F, typename... Args>
  void callback_dispatcher(F call, Args&& ...args )
  {   
    std::cout << "callback_dispatcher>" << __PRETTY_FUNCTION__ << "enter <<< " << std::endl;                                                 
    auto invoke_me = [tup = std::make_tuple(std::forward<Args>(args)...), call=std::move(call)]()mutable{
      std::apply( call, std::move(tup) );
    };  
    invoke_me();
  }   

where you now have to implement std::apply, which is a C++17 feature, in the limited subset of C++11 you have. (Don't call it std::apply). This approach will probably work in g++ 4.8.

namespace notstd {
  template<std::size_t...Is> struct index_sequence {using type=index_sequence;};
  template<std::size_t N, std::size_t...Is> struct make_index_sequence:make_index_sequence<N-1, N-1, Is...>{};
  template<std::size_t...Is> struct make_index_sequence<0,Is...>:index_sequence<Is...>{};
  namespace details {
    template<class F, class Tuple, std::size_t...Is>
    auto apply( ::notstd::index_sequence<Is...>, F&& f, Tuple&& tuple )
    -> decltype( std::declval<F>()( std::get<Is>(std::declval<Tuple>())... ) )
    {
      return std::forward<F>(f)( std::get<Is>(std::forward<Tuple>(tuple))... );
    }
  }
  template<class F, class Tuple>
  auto apply( F&& f, Tuple&& tuple )
  -> decltype(::notstd::details::apply( make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{}, std::forward<F>(f), std::forward<Tuple>(tuple) ))
  {
    return ::notstd::details::apply( make_index_sequence<std::tuple_size<typename std::decay<Tuple>::type>::value>{}, std::forward<F>(f), std::forward<Tuple>(tuple) );
  }
}

live example of C++11 compliant notstd::apply.

I am also getting same error with c++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-36) with c++11

template<typename... Args>
    void emplace_front(Args&&... args)
    {
        target( [&] {
                     _collection.emplace_front(std::forward<Args>(args)...);
                     } );
    }

following worked for me!

template<typename... Args>
    void emplace_front(Args&&... args)
    {
        target( [&] (Args ...ar) -> void {
                           _collection.emplace_front(ar...);
                           } );
    }

i get warning for Args&&... args as unused but easy to fix that.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!