2

から除外しますfooには、fooのバリデーションテンプレートに渡されるタイプのサブセットを持つbarという関数を呼び出します。例:最初のn個の引数をパラメータパック

template <typename... T> 
void foo() { 
    // ... 
    template <size_t start_idx, typename... T> 
    using param_pack = /*Parameter pack with T[start_idx]...T[N]*/ 
    auto b = bar<param_pack<2, T...>>(); 
    // ... 
} 

「サブパラメータパック」を抽出する方法はありますか?上記の場合 T = [int float char double]場合、param_pack<2, T...> = [char double]

[EDIT]

私の目標は、イベントハンドラを一致させるために、このようなものを使用することができることです。例えば、ここで

struct ev {}; 

template <typename... T> 
struct event : ev { 
    std::tuple<T...> data_; 

    event(T&&... d) : data_(std::make_tuple(std::forward<T>(d)...)) {} 
}; 

template <typename... Functor> 
struct handler { 
    std::tuple<Functor...> funcs_; 

    handler(Functor&&... f) : funcs_(std::make_tuple(std::forward<Functor>(f)...)) {} 

    void handle_message(ev* e) { 
    auto ptrs = std::make_tuple(
     dynamic_cast<event<param_pack<1, typename function_traits<F>::args>>*>(e)... 
    ); 

    match(ptrs); 
    } 
}; 

function_traits::argsはタプルfuncs_dynamic_castが成功したかどうかをチェックし、最初に成功した機能を実行するオーバー関数の引数とマッチ繰り返し処理のためのパラメータパックを取得します。私はすでにこれらを実装しています。

ハンドラは、私は基本的にself引数を取り除くためにしようとしています

[] (handler* self, <ARGS>) -> void { 
    // ... 
} 

のようなものです。

+0

関連する質問:https://stackoverflow.com/questions/8569567/get-part-of-stdtuple – keith

+0

おっと...私の悪い...私が実装しようとした – subzero

答えて

3

は、ここでは(ない定義は必要ありません)と関数宣言に基づき、可能な解決策であります宣言を使用:

template<std::size_t N, typename... T, std::size_t... I> 
std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...> 
sub(std::index_sequence<I...>); 

template<std::size_t N, typename... T> 
using subpack = decltype(sub<N, T...>(std::make_index_sequence<sizeof...(T) - N>{})); 

良い部分、このアプローチのあなたはタプルを中心に設計された新しいタイプを導入していないことで、その後、何とか繰り返し、それを専門としています。


それは上記のコードを使用して、最小限の作業例を次に示します。

#include<functional> 
#include<tuple> 
#include<cstddef> 
#include<type_traits> 

template<std::size_t N, typename... T, std::size_t... I> 
std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...> 
sub(std::index_sequence<I...>); 

template<std::size_t N, typename... T> 
using subpack = decltype(sub<N, T...>(std::make_index_sequence<sizeof...(T) - N>{})); 

int main() { 
    static_assert(std::is_same<subpack<2, int, float, char, double>, std::tuple<char, double>>::value, "!"); 
} 

完全な例までとwandbox上で実行しているを参照してください。


Nは次のようになり、インデックスのチェック含む拡張版:

template<std::size_t N, typename... T, std::size_t... I> 
std::enable_if_t<(N < sizeof...(T)), std::tuple<std::tuple_element_t<N+I, std::tuple<T...>>...>> 
sub(std::index_sequence<I...>); 

あなたがもう一度std::enable_if_t、何に包まれた最初の例で見ることができるタイプです。ここでも宣言だけで十分です。定義は必要ありません。


EDIT

あなたの代わりにstd::tupleの独自のクラステンプレートを使用する場合は、簡単にそれを行うためのコードを変更することができます。

#include<functional> 
#include<tuple> 
#include<cstddef> 
#include<type_traits> 

template<typename...> 
struct bar {}; 

template<template<typename...> class C, std::size_t N, typename... T, std::size_t... I> 
std::enable_if_t<(N < sizeof...(T)), C<std::tuple_element_t<N+I, std::tuple<T...>>...>> 
sub(std::index_sequence<I...>); 

template<template<typename...> class C, std::size_t N, typename... T> 
using subpack = decltype(sub<C, N, T...>(std::make_index_sequence<sizeof...(T) - N>{})); 

int main() { 
    static_assert(std::is_same<subpack<bar, 2, int, float, char, double>, bar<char, double>>::value, "!"); 
} 

EDIT

質問に追加されたコードによれば、上記の解決策はまだ有効です。それは次のようにあなたは自分のeventクラスを定義する必要があります

struct ev {}; 

template <typename> 
struct event; 

template <typename... T> 
struct event<std::tuple<T...>>: ev { 
    // ... 
}; 

この方法は、あなたがこれを行うとき:

event<param_pack<1, typename function_traits<F>::args>> 

あなたはまだparam_packのうちのタプルを取得する(つまり、私の中で宣言を使用してsubpackです例)ですが、テンプレート部分指定eventと一致し、パラメータパックはT...として自由に使用できます。

これは、使用する宣言にパラメーターパックを入れることができないため、これが可能です。とにかくそれはちょうど働くので、おそらくそれはあなたの問題を解決することができます。

+0

タイプは 'std :: tuple 'です。つまり、 'T ...'を直接取得する方法はありますか? – subzero

+0

@subzero使用する宣言にパックを入れてください。あなたができるものは、他のデータと一緒に入れたいタイプを渡し、タプルではなく元に戻すことです。あなたのために働くことができますか?そのパックをどのように使いたいですか? – skypjack

+0

@subzero独自のクラステンプレートをどのように使用できるかを示す別の例を追加しました。 – skypjack

2

あなたが何かやることがあります。それは簡単にするために、インデックスNのチェックを欠いているという事実を脇に置きます

template <std::size_t N, typename ... Ts> struct drop; 

template <typename ... Ts> 
struct drop<0, Ts...> 
{ 
    using type = std::tuple<Ts...>; 
}; 

template <std::size_t N, typename T, typename ... Ts> 
struct drop<N, T, Ts...> 
{ 
    using type = typename drop<N - 1, Ts...>; 
}; 

// Specialization to avoid the ambiguity 
template <typename T, typename... Ts> 
struct drop<0, T, Ts...> 
{ 
    using type = std::tuple<T, Ts...>; 
}; 
+0

今編集を作りますこれはコンパイラが 'N = 0'の特殊化を選択できないという事実に似ています。あなたは見てみることができます:https://wandbox.org/permlink/u3QOECdxokexLgyG –

+0

@ EdgarRokyan:確かに、特別な専門が必要です。 [固定版](https://wandbox.org/permlink/K0Bb3MwjwTtJFU8x)。 – Jarod42

+0

パーフェクト、ありがとう!現在、少し厄介なように見えますが、( –

0

ここではすばらしいが、特に再利用可能な解決策はありません。

template <typename Pack, std::size_t N, std::size_t... Is> 
void invoke_bar_impl(std::index_sequence<Is...>) { 
    bar<std::tuple_element_t<N + Is, Pack>...>(); 
} 

template <std::size_t N, typename... Ts> 
void invoke_bar() { 
    auto indices = std::make_index_sequence<sizeof...(Ts) - N>(); 
    invoke_bar_impl<std::tuple<Ts...>, N>(indices); 
} 
関連する問題