2016-08-03 24 views
6

Mam funkcję tak:Jak utworzyć niestandardową sekwencję liczb całkowitych w C++

template <typename ... Types> 
void foo(const Types & ... values) 
{ 
    // expected that 'values' is sequence like 
    // '1, customvalue1, 2, customvalue2, 3,...' 
} 

a po drugie funkcję:

template <typename ... Types> 
void bar(const Types & ... values) 
{ 
    // where 'values' are any variables 
    // some magic here 
    foo((int_seq<sizeof...(Types)>, values)...); 
} 

Chciałbym przekazać dowolną sekwencję zmiennych pasku, aby ta sekwencja przekształciła się w sekwencję taką jak '1, wartość1, 2, wartość2, 3, wartość3'. Zatem każda wartość podąża za jej liczbą w sekwencji bazowej. Ale nie mogę utworzyć tego "magicznego kodu" ", aby przekształcić sekwencję w fazie kompilacji między tymi dwoma stanami.

+2

Zakładam, że 'bar' ma nazywać' foo'? Nie wywołuje się rekursywnie? –

+0

czy spojrzałeś na tablicę asocjacyjną? To wydaje się być problemem dla tego typu struktury danych. –

+0

Tak, myliłem się, to oczywiście 'foo', a nie 'bar'. –

Odpowiedz

1

Nie bardzo elegancki, ale przy użyciu krotki, std::tie, itp ...

Poniższy przykład powinien współpracować z C++ 11

--- EDIT ---

Zmodyfikowany i ujednolicony (C++ 11 bez elementów C++ 14) mój pierwszy przykład.

Nie ma potrzeby std::index_sequence (trywialne struct indSeq można stosować zamiast) lub std::make_index_sequence (sekwencja indeks może być contructed krok po kroku stosując sizeof...(I)); nie będzie już potrzeby więcej niż qux().

#include <tuple> 
#include <iostream> 


void foo() 
{ } 

template <typename T0, typename ... Types> 
void foo (const T0 & v0, const Types & ... values) 
{ 
    std::cout << "-- " << v0 << std::endl; 

    foo(values...); 
} 


template <std::size_t ...> 
struct indSeq 
{ }; 

template <std::size_t ... Is, typename ... Ts1> 
void baz (std::size_t, const indSeq<Is...> &, const std::tuple<Ts1...> & t) 
{ foo(std::get<Is>(t)...); } 

template <std::size_t ... Is, typename ... Ts1, typename T0, typename ... Ts2> 
void baz (std::size_t n, const indSeq<Is...> &, const std::tuple<Ts1...> & t, 
      const T0 & v0, const Ts2 & ... vs) 
{ baz(n+1U, indSeq<Is..., sizeof...(Is), sizeof...(Is)+1U>(), 
     std::tuple_cat(t, std::tie(n), std::tie(v0)), vs...); } 

template <typename ... Types> 
void bar (const Types & ... values) 
{ baz (1U, indSeq<>(), std::tuple<>(), values...); } 

int main() 
{ 
    bar(11, 22L, "33", 44.44); 
    return 0; 
} 

p.s .: przepraszam za mój zły angielski.

2

Oto rozwiązanie C++ 14, ale wszystkie niezbędne części biblioteki można również napisać w C++ 11.

#include <iostream> 
#include <tuple> 
#include <utility> 

template <typename ... Types> 
void foo(const Types & ... values) 
{ 
    using swallow = bool[]; 
    (void)swallow{ (std::cout << values << std::endl,false)... }; 
} 

template <std::size_t N, bool = (N%2==0)> 
struct pick { 
    template<typename... Types> 
    static std::size_t get(const std::tuple<Types...>&) { return N/2; } 
}; 

template <std::size_t N> 
struct pick<N,false> { 
    template<typename... Types> 
    static auto get(const std::tuple<Types...>& t) { return std::get<N/2>(t); } 
}; 

template <std::size_t... Indices, typename ... Types> 
void bar2(const std::index_sequence<Indices...>, const Types & ... values) 
{ 
    auto x = std::tie(values...); 
    foo(pick<Indices>::get(x)...); 
} 

template <typename ... Types> 
void bar(const Types & ... values) 
{ 
    bar2(std::index_sequence_for<Types...,Types...>(), values...); 
} 

int main() 
{ 
    bar("Hallo", 42, 1.23); 
} 

Live example

Jest zera obecnie, ale +1 we właściwym miejscu, aby rozwiązać tak łatwo. Tworzy także pośrednie std::tuple z odniesieniami do wartości, jeśli wydajność jest problemem, mogą istnieć lepsze opcje, ale ponieważ nie używasz std::forward, uznałem, że mały wpływ na wydajność może być dla ciebie akceptowalny.

+0

Znalazłbym zrobienie krotek-2-krotek, a następnie spłaszczenie, aby być moim domyślne podejście. W C++ 17 mogłem użyć 'if constexpr',' tupler', lambda i 'std :: apply', aby wykonać wywołanie inline, co byłoby naprawdę zabawne. – Yakk

Powiązane problemy