2014-09-03 76 views
0

我寫了這樣的一些代碼,編譯罰款:你如何迭代元組?

#include <tuple> 

template <typename... Args> 
class Functions 
{ 
    // stuff 
public: 
    Functions(Args... args) 
    { 
     tuple<decltype(args)...> t{args...}; 
     auto begin = begin(t); 
     auto end = end(t); 
     auto it = begin; 
     while (it != end) 
     { 
      cout << *it; 
     } 
    } 
}; 

在嘗試使用它,雖然我可以看到,它實際上並沒有正常工作。有沒有辦法使用標準庫函數迭代元組?

+1

我不這麼認爲。考慮到元組元素可以是不同的類型,那麼'* it'表達式應該是什麼類型?通常,您需要遞歸模板實例來遍歷參數包 - 您需要在編譯時「循環」,而不是在運行時。 – 2014-09-03 02:56:18

+0

C++ 14使這更容易。 – Yakk 2014-09-03 03:01:16

+0

有索引的'for'循環會爲您工作,而不是您的經典迭代器,但會循環使用相同的效果? – Niall 2014-09-03 05:37:38

回答

3

有幾種方法可以做到這一點。一種方法我想可以用這個模板整齊展開技巧:

auto l = {0, ((std::cout << args), 0)...}; 
(void)l; 

的好處是,你不需要元組和其相對短相比其他方法。

如果您仍需要元組,你可以使用indicies通過索引來訪問的元組元素:

template<int... Indices> 
struct indices { 
    typedef indices<Indices..., sizeof...(Indices)> next; 
}; 

template<int N> 
struct build_indices { 
    typedef typename build_indices<N - 1>::type::next type; 
}; 

template<> 
struct build_indices<0> { 
    typedef indices<> type; 
}; 

template<int n> 
using build_indices_t = typename build_indices<n>::type; 

template<typename... Args> 
class Functions 
{ 
public: 
    Functions(Args... args) 
     : Functions(std::make_tuple(args...), 
        build_indices_t<sizeof...(Args)>()) 
    { } 
private: 
    template<typename... Ts, int... Is> 
    Functions(const std::tuple<Ts...>& tup, indices<Is...>) 
    { 
     print(std::get<Is>(tup)...); 
    } 

    void print() { } 

    template<class Head, class... Tail> 
    void print(Head&& head, Tail&&... tail) 
    { std::cout << head; print(tail...); } 
}; 
+1

這是幹什麼的,它是如何工作的? – 2014-09-03 03:00:45

+0

@MiyazawaKenji表達式'std :: cout << args'只是對包中的每個參數都重複(感謝放置'...')。第一個0表示'args'爲空,第二個基本上忽略'operator <<()'返回的所有內容,並用int替換它。因此'l'是一個'std :: initializer_list ',所有值都是'0'。轉換爲'void'是爲了避免任何有關未使用變量的警告。 – 0x499602D2 2014-09-03 03:06:45

+0

骯髒的把戲,但soooo短,投票:) – 2014-09-03 03:09:48