簡體   English   中英

c++中使用了部分模板參數包的function如何調用?

[英]How to call function that use part of template parameter pack in c++?

我有以下問題:

我想創建可變參數模板 class,它必須調用 lambda,它可能采用模板參數包的前 N 個參數(N 可能從 0 到參數包的大小不等,並且因不同的 lambda 而異)。

我認為,遞歸模板助手 function 將檢查 lambda 是否可調用,從所有參數開始,應該是最好的變體,但我如何將參數包中除最后一個參數之外的所有參數傳遞給它,這是否可能?

目前我認為它是這樣的:

template< typename Callable, typename ...Args >
void Call( Callable& cb, Args... args )
{
   using Function = std::remove_reference_t< Callable >;
   if constexpr( std::is_invocable_v< Function, Args... > )
      cb( args... );
   else if constexpr( sizeof...( args ) == 0 )
      cb();
   else
   {
      // Here I want to create shortened_args, that are all args but last one.
      // Call( cb, shortened_args... );
   }
}

UPD:我沒有先提到它,但我需要 C++17 解決方案。

您可以使用std::index_sequence作為助手:

template <typename Callable, typename Tuple, std::size_t... Is>
constexpr std::size_t is_invocable_args(std::index_sequence<Is...>)
{
    return std::is_invocable_v<Callable, std::tuple_element_t<Is, Tuple>...>;
}

// Helper to know max number of args to take from tuple
template <typename Callable, typename Tuple, std::size_t... Is>
constexpr std::size_t max_invocable_args(std::index_sequence<Is...>)
{
    std::array<bool, sizeof...(Is)> a = {
        is_invocable_args<Callable, Tuple>(std::make_index_sequence<Is>{})...
        };
    auto rit = std::find(a.rbegin(), a.rend(), true);
    if (rit == a.rend()) throw "no valid call";
    return std::distance(a.begin(), rit.base()) - 1;
}

template <std::size_t N, typename Callable, typename Tuple>
constexpr std::size_t max_invocable_args()
{
    return max_invocable_args<Callable, Tuple>(std::make_index_sequence<N + 1{});
}

// Call taking some element from tuple
template< typename Callable, std::size_t... Is, typename Tuple >
void Call_Tuple_impl(Callable cb, std::index_sequence<Is...>, Tuple&& args )
{
    std::invoke(cb, std::get<Is>(std::forward<Tuple>(args))...);
}

template< typename Callable, typename ...Args >
void Call( Callable cb, Args... args )
{
    constexpr std::size_t max_arg_count = max_invocable_args<sizeof...(Args), Callable, std::tuple<Args...>>();

    Call_Tuple_impl(cb, std::make_index_sequence<max_arg_count>{}, std::forward_as_tuple(std::forward<Args>(args)...));
}

C++20 演示
C++17重寫constexpr find的演示。

把它分成兩部分。 首先,確定有多少 arguments。然后用那么多 arguments 調用。

template<class Tup, std::size_t...Is>
auto slice_tuple(Tup tup, std::index_sequence<Is...>){
  using std::get;
  return std::make_tuple(get<Is>(std::forward<Tup>(tup))...);
}
template<std::size_t N, class Tup>
auto front_of_tuple(Tup tup){
  return slice_tuple(std::forward<Tup>(tup), std::make_index_sequence<N>{});
}

將args打包成元組,獲取前面的N,然后std apply。

要完善轉發/避免復制,請使用參考包裝器。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM