2016-08-03 21 views
6

我有這樣的功能:如何在C創建自定義的整數序列++

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

和二級功能:

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

我想變數任何序列傳遞給酒吧,使得該序列轉換成如'1,值1,2,值2,3,值3'的序列。所以每個值都以基數序列跟隨它的數字。但我無法創建這個'魔術碼'在這兩個狀態之間的編譯階段轉換序列。

+2

我假設'bar'應該叫'foo'?不是自己遞歸調用? –

+0

你看過關聯數組嗎?這似乎是這種類型的數據結構的問題 –

+0

是的,我錯了,它當然是'富',而不是'酒吧' –

回答

1

不是真的優雅,但使用的元組,std::tie等..

下面的例子應該與C++ 11

---編輯工作---

修改和統一(C++ 11沒有C++ 14元素)我的第一個例子。

沒有必要的std::index_sequence(微不足道struct indSeq可以用來代替)或std::make_index_sequence(索引序列可以池莉構建步驟通過使用sizeof...(I)步驟);不再需要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; 
} 

對不起,我的英語不好。

2

下面是一個C++ 14解決方案,但所有必需的庫部件也可以用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

這是目前從零開始,而是在正確的地方會解決,很容易一+1。此外,它創建了一箇中間值std::tuple,並引用了這些值,如果性能是一個問題,那麼可能存在更好的選項,但由於您沒有使用std::forward,我認爲對您而言性能影響可能不大。

+0

我會發現製作一個2元組的元組,然後展平,成爲我的默認方法。在C++ 17中,我可以使用'如果constexpr','tupler',lambda和'std :: apply'來進行內聯調用,這將非常有趣。 – Yakk

相關問題