2017-08-18 8 views
0

適用するために渡すことができる関数オブジェクトを定義するにはどうすればよいですか?最終的には、タプルのすべての要素をとり、それらをベクトルに戻す関数F fが必要です。バリデーションテンプレートを使用する関数オブジェクト

template <class F, size_t... Is> 
constexpr auto index_apply_impl(F f, index_sequence<Is...>) { 
    return f(integral_constant<size_t, Is> {}...); 
} 

template <size_t N, class F> 
constexpr auto index_apply(F f) { 
    return index_apply_impl(f, make_index_sequence<N>{}); 
} 

template <class Tuple, class F> 
constexpr auto apply(Tuple t, F f) { 
    return index_apply<tuple_size<Tuple>{}>(
     [&](auto... Is) { return f(get<Is>(t)...); }); 
} 

感謝:)

+0

アイデアは非常にいいですが、それは何のベクトルでしょうか? –

+0

[反復処理]の可能な複製(https://stackoverflow.com/questions/1198260/iterate-over-tuple) – Justin

+0

重複していません。この特定の質問には答えがありません。なぜなら、結果を保持できる唯一の種類のベクトルのようなものは、入力のコピーであるタプルになるからです。 –

答えて

1

あなたはexpander trickを使用することができます。これはC++ 14が必要です。私はあなたのバイト配列形式のように見えるか分からないので、私はちょうど文字列メンバで汎用構造体を取って、コンストラクタ内のすべての文字列に変換します。 C++ 17では


Live example

#include <iostream> 
#include <string> 
#include <tuple> 
#include <vector> 

template < typename T, typename F, size_t ... Is > 
void for_each_impl(T&& t, F&& f, std::index_sequence<Is...>) 
{ 
    using expand_type = int[]; 
    (void) expand_type { 0, ((void) f(std::get<Is>(t)), 0) ... }; 
} 

template < typename... Args, typename F > 
void for_each(std::tuple<Args...> const& t, F&& f) 
{ 
    for_each_impl(t, f, std::make_index_sequence<sizeof...(Args)>{}); 
} 


struct Bytes { 
    std::string str; 
    Bytes(char const * c) : str(c) {}; 
    Bytes(int i) : str(std::to_string(i)) {}; 
    Bytes(char c) : str(1, c) {}; 
}; 


int main() 
{ 
    auto t = std::make_tuple(12, "abc", 10, 'c', 1); 
    std::vector<Bytes> v; 
    for_each(t, [&v](auto&& x){ v.push_back(x); }); 

    for (auto const& e : v) 
    std::cout << e.str << ' '; 
    std::cout << '\n'; 
} 
それは、可変長ラムダ、 fold expression、および std::applyのおかげで非常に簡単です。あなたがC++ 11を使用することができない場合は


Live example

#include <iostream> 
#include <string> 
#include <tuple> 
#include <vector> 

struct Bytes { 
    std::string str; 
    Bytes(char const * c) : str(c) {}; 
    Bytes(int i) : str(std::to_string(i)) {}; 
    Bytes(char c) : str(1, c) {}; 
}; 


int main() 
{ 
    auto t = std::make_tuple(12, "abc", 10, 'c', 1); 
    std::vector<Bytes> v; 
    std::apply([&v](auto&&... x){ (... , v.push_back(x)); }, t); 

    for (auto const& e : v) 
    std::cout << e.str << ' '; 
    std::cout << '\n'; 
} 
あなたの人生は苦痛になります。あなたは index_sequenceという独自の実装をロールバックしなければならず、ジェネリックラムダを置き換えるために、テンプレート付きコール演算子でヘルパー構造体を定義する必要があります。

#include <iostream> 
#include <string> 
#include <tuple> 
#include <vector> 

// https://stackoverflow.com/a/24481400/1944004 
template <size_t ...I> 
struct index_sequence {}; 

template <size_t N, size_t ...I> 
struct make_index_sequence : public make_index_sequence<N - 1, N - 1, I...> {}; 

template <size_t ...I> 
struct make_index_sequence<0, I...> : public index_sequence<I...> {}; 


// Call a function for each element in a tuple 

template < typename T, typename F, size_t ... Is > 
void for_each_impl(T&& t, F&& f, index_sequence<Is...>) 
{ 
    using expand_type = int[]; 
    (void) expand_type { 0, ((void) f(std::get<Is>(t)), 0) ... }; 
} 

template < typename... Args, typename F > 
void for_each(std::tuple<Args...> const& t, F&& f) 
{ 
    for_each_impl(t, f, make_index_sequence<sizeof...(Args)>{}); 
} 

// "Byte array" emulation 

struct Bytes { 
    std::string str; 
    Bytes(char const * c) : str(c) {}; 
    Bytes(int i) : str(std::to_string(i)) {}; 
    Bytes(char c) : str(1, c) {}; 
}; 

// Surrogate template lambda 

struct Visitor 
{ 
    std::vector<Bytes>& v; 
    Visitor(std::vector<Bytes>& vb) : v(vb) {}; 
    template < typename T > 
    void operator() (T&& x) { v.push_back(x); } 
}; 


int main() 
{ 
    auto t = std::make_tuple(12, "abc", 10, 'c', 1); 
    std::vector<Bytes> v; 
    for_each(t, Visitor(v)); 

    for (auto const& e : v) 
    std::cout << e.str << ' '; 
    std::cout << '\n'; 
} 

Live example

+0

ありがとうHenri!それは華麗でした! C++ 11でこれを達成する方法はありますか? – A03

+0

@ a03はい、ラムダを 'template'の' operator() 'でオブジェクトとして書き換えます。 – Yakk

+0

@ A03最新の回答をご覧ください。 –

関連する問題