2016-07-21 40 views
10

varsayalım I aynı zamanda yineleme için isteyen 2 (veya daha fazla) konteyner - örneğin, iki vektörün nokta ürününü hesaplamak için:sınıf

std::vector<double> vector1; 
std::vector<double> vector2; // identical size to vector1 

tercih C + ne Her iki (veya tümü) kapsayıcıda eşzamanlı bir döngü belirtmek için +11 yolu aynı anda mı? Tüm diğer kaplar/yineleyicilerin uzun elle ele alınması gerektiğinde, kısa mesafeli (yani for (auto i : c)) bir aralıkta yazma için bir kapsayıcı/yineleyicinin seçilmesini gerektiriyor mu? (Sıklıkla fonksiyonel) Diğer dillerde

double dotProduct(0.0); 
for (auto const & value1 : vector1, auto const & value2 : vector2) // illegal! 
{ 
    dotProduct += value1*value2; 
} 
+3

Olası iki kopyası [Aynı anda iki veya daha fazla kapsayıcının üzerinde yineleme yapmanın en iyi yolu nedir?] (Http://stackoverflow.com/questions/12552277/whats-the-best-way-to-iterate-over-two-or - Daha fazla kaplar-eş zamanlı olarak) – ildjarn

+0

Yüzeyde, evet ... ama cevaplardan herhangi biri (a) okunabilir ve (b) genel ve (c) standart C++? Gördüğümden değil. C'nin ilk günlerinden biri için (i = 0, j = 0, k = 0; i omatai

+0

[miterator] 'a bir göz atın (https://github.com/ClaasBontus/miterator). C++ 20'den önce olmayacak olan aralıklarla daha kolay hale gelecektir. –

cevap

7

Bu yapıldığında: gerçekten okunabilir görünüyor aşağıda gösterildiği gibi gelecekte sözdizimi ikisi için/tüm kapları kısa elini destek amaçlı olarak değil bir neden ... var mı zip adlı bir işlev kullanarak.

for i in zip([1,2,3], (1,2,3), { 0:0, 1:1, 2:2 }): 
    l,t,d = i 
    print("list item: %d, tuple item %d, dict item %d" % (l,t,d))  

Sen, mesela bu işlevselliği elde etmek C++ bir dizi kütüphanesini kullanabilirsiniz: Örnek olarak, Python bir demet bağımsız değişkenler üzerinde üzerinde dolaşır yerleşik bir zip vardır ve döner Boost.Range veya Eric Niebler's rangev3. Aralıklar maalesef C++ 17 standardında oy kullanmamıştı ancak asla bir dizi kütüphanesi olmayan bir projeye başlamamıştım. Boost.Range olarak işlev combine denir:

#include <boost/range/combine.hpp> 
#include <iostream> 
#include <vector> 
#include <list> 

int main(int, const char*[]) 
{ 
    std::vector<int> const v{0,1,2,3,4}; 
    std::list<char> const l{'a', 'b', 'c', 'd', 'e'}; 

    for(auto const& i: boost::combine(v, l)) 
    { 
     int ti; 
     char tc; 
     std::tie(ti,tc) = i; 
     std::cout << '(' << ti << ',' << tv << ')' << '\n'; 
    } 

    return 0; 
} 

17 C++ ile yapılandırılmış bağlama ile std::tie değiştirip std::tie ile olağandışı "başlatma" tür kaldırabilirsiniz. Ben aralıkları C++ 17 yer almayan pişman olsa

for(auto const& [ti,tc] : boost::combine(v, l)) { 
    std::cout << '(' << ti << ',' << tv << ')' << '\n'; 
    } 

, ben yapılandırılmış bağlamaları büyük ilerleme ve ciddi şekilde kod yazılır değişeceğini düşünüyorum. Standartta yer almak, onları daha popüler hale getirecek ve onları C++ programcısının bilmesi gereken standart bir özellik olarak bilmedikleri bir şey olduğu için birçok kişinin itiraz ettiği bir üçüncü parti kütüphanesinden yükseltecektir.

+0

Mükemmel bir cevap ... ama biraz hayal kırıklığı. Ve olmamalıydı 'std :: kravat (ti, tc) = ı'? Bu konuda tatminsiz buluyorum, sizin hatalarınız değil - (a) hileleri ve (c) tek bir yineleyici kullanarak ... (basit) çoklu eşzamanlı yineleyiciler yerine (a) şeyleri bir araya getirerek (a) yoğun bir şekilde yönlendiren C++ sözdiziminin hatasıdır. . Benim soruya yorumumda gösterilen orijinal C sözdizimi göz önüne alındığında, C++ (int i = 0, int j = 0; j = 0; ...) '. Neden olmasa bile zorlayıcı bir sebep olup olmadığını merak ediyorum. – omatai

+0

@omatai neden hayal kırıklığı yaratıyor? Boost :: C++ 98 kodunda bile kullanabilirsiniz. "Hileler" ile ilgili olarak - Python versiyonuna bakın - bazı şeyleri birleştirmek için de "hile" vardır, hatta Haskell zip "hilesi" vardır.Ve bunun dezavantaj olduğunu sanmıyorum - neden kütüphaneleri kolayca uygulayabileceğiniz bir şeyle dili kirletmek? –

+0

Okunabilirlik, dağınıklık. Eğer önerdiğim (yasadışı) kodumla veya beş yıl içinde bu kodla karşılaşırsam, öneri ile ne olduğunu anında anlardım ve bunu özümsemek için çok daha fazla beyin gücü ve inanç sıçramaları uygulamak zorundayım (tamamen geçerli) versiyon (@Jens'e karşı saldırı). Öyleyse bu (tamamen geçerli) cevapta değil, C++ sözdiziminin daha basit ve daha temiz olacağını düşündüğüm bir şeyi desteklememesinden dolayı hayal kırıklığına uğradım. – omatai