簡體   English   中英

基於范圍的循環可以知道結束嗎?

[英]Can range-based for loops be aware of the end?

給出最小的C ++ 11 STL示例:

set<int> S = {1,2,3,4};
for(auto &x: S) {    
   cout << x;
   cout << ",";
}

有沒有辦法檢查x是否在結束之前? 此示例中的目標是輸出1,2,3,4而不是最后的最后一個逗號。 目前我使用帶有兩個迭代器的標准for循環,

set<int>::const_iterator itr;
set<int>::const_iterator penultimate_end_itr = --S.end();
for(itr=S.begin(); itr!=penultimate_end_itr;++itr) 
    cout << (*itr) << ',';
cout << (*penultimate_end_itr);

哪個有效,但非常麻煩。 有沒有辦法在基於范圍的for循環中進行檢查?

編輯:問題的關鍵是打印逗號分隔列表。 我想知道基於范圍的for循環是否具有列表中倒數第二個元素的任何知識(即它是在結束之前的一個)。 提出了最小的例子,所以我們都有一個共同的代碼塊來討論。

基於范圍的for循環的目的是忘記迭代器。 因此,它們只允許您訪問當前值而不是迭代器。 以下代碼會為您執行此操作嗎?

set<int> S = {1,2,3,4};

std::string output;
for(auto &x: S) {    
   if (!output.empty())
       output += ",";
    output += to_string(x);
  }

cout << output;

編輯

另一個解決方案:您可以比較值的地址,而不是比較迭代器(就像循環的“正常”)。

set<int> S = {1,2,3,4};
auto &last = *(--S.end());
for (auto &x : S)
{
    cout << x;
    if (&x != &last)
        cout << ",";
}

Boost.Range可以在這里提供幫助:

if (std::begin(S) != std::end(S)) {
    std::cout << *std::begin(S);
    for (const auto &x: boost::make_iterator_range(std::next(std::begin(S)), std::end(S))) {
        std::cout << ", " << x;
    }
}

一種更靈活的方法是使用boost::adaptors::indexed (自Boost 1.56起) boost::adaptors::indexed范圍:

for (const auto &element: boost::adaptors::index(S)) {
    std::cout << (element.index() ? ", " : "") << element.value();
}

在1.56之前的Boost版本中,boost boost::adaptors::indexed將不起作用,但您可以輕松編寫類似的工作:

template <typename... T>
auto zip(const T&... ranges) -> boost::iterator_range<boost::zip_iterator<decltype(boost::make_tuple(std::begin(ranges)...))>>
{
    auto zip_begin = boost::make_zip_iterator(boost::make_tuple(std::begin(ranges)...));
    auto zip_end = boost::make_zip_iterator(boost::make_tuple(std::end(ranges)...));
    return boost::make_iterator_range(zip_begin, zip_end);
}

template<typename T>
auto enumerate(const T &range) -> boost::iterator_range<boost::zip_iterator<boost::tuple<
    boost::counting_iterator<decltype(boost::distance(range))>, decltype(std::begin(range))>>>
{
    return zip(boost::make_iterator_range(boost::make_counting_iterator(0),
        boost::make_counting_iterator(boost::distance(range))), range);
}

for (const auto &tup: enumerate(S)) {
    std::cout << (tup.get<0>() ? ", " : "") << tup.get<1>();
}

這是使用zip從功能的C ++ 11序列-zip函數?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM