Soru Brace-kapalı başlatıcı listesi kurucu


Aşağıdaki kurucu ile sınıf Phenotype var:

Phenotype(uint8 init[NUM_ITEMS]);

Böyle bir Fenotip oluşturabilirim:

uint8 data[] = {0,0,0,0,0};
Phenotype p(data);

Ama böyle bir tane oluşturmaya çalıştığımda bir hata alıyorum:

Phenotype p = {0,0,0,0,0};

Çıktı:

$ make
g++ -Wall -g main.cpp -std=c++0x
main.cpp: In function ‘int main(int, char**)’:
main.cpp:109: error: no matching function for call to ‘Phenotype::Phenotype(<brace-enclosed initializer list>)’
main.cpp:37: note: candidates are: Phenotype::Phenotype(uint8*)

Hata, ayracı kapalı başlatıcı listesi alan bir kurucu tanımlamanın bir yolu olduğunu gösteriyor gibi görünüyor. Bunun nasıl yapılacağını bilen var mı?


41
2017-11-07 13:57


Menşei


olası kopyası Bu sözdizimi tarafından işlevlere argüman olarak dizileri, yaklaşan c ++ 0x standartları altında geçirebilir miyiz? - kennytm


Cevaplar:


Sadece agregalar için yapılabilir (diziler ve belirli sınıflar. Popüler inanışın aksine, bu pek çok nonpod için de geçerlidir). Onları alan bir kurucu yazmak mümkün değil.

Bunu "C ++ 0x" olarak etiketlediğinizden, bu olsa da mümkündür. Sihirli kelimeler "başlatıcı listesi oluşturucu" dır. Bu gibi gider

Phenotype(std::initializer_list<uint8> c) {
  assert(c.size() <= std::size(m_array));
  std::copy(c.begin(), c.end(), m_array);
}

// used like
Phenotype p1{1, 2, 3};
Phenotype p2({1, 3, 2}); // works too
Phenotype p3(1, 2, 3); // doesn't work

Bununla birlikte, böyle bir başlatma diziyi varsayılan olarak kurar ve ardından görevlendiriciyi kullanır. Hız ve güvenliği hedefliyorsanız (çok fazla başlatıcı için derleme zamanı hataları elde edersiniz!), Aynı zamanda değişken bir şablonla sıradan bir kurucu kullanabilirsiniz.

Bu, ihtiyaç duyulandan daha genel olabilir (genellikle bir tamsayı listesi tamamen düz tamsayılar için yeterlidir). Mükemmel bir yönlendirmeden yararlanır, böylece bir dizi argümanı bir dizi elemanına yerleştirilebilir

template<typename ...T>
Phenotype(T&&...t):m_array{ std::forward<T>(t)... } {

}

// used like
Phenotype p1{1, 2, 3}; 
Phenotype p2(1, 2, 3); // works too
Phenotype p3({1, 2, 3}); // doesn't work   

Bu zor bir seçim!

Düzenle Düzeltme, sonuncusu da çalışıyor, çünkü kurucuyu yapmadık explicitbu yüzden kopya kurucusunu kullanabilir Phenotypegeçici olarak inşa etmek Phenotype nesne ve üzerine kopyala p3. Ama bu gerçekten aramaların olmasını istediğimiz şey değil :)


67
2017-11-07 14:05



Çok yararlı. Bir süreliğine bunun cevabını bekliyorum. - Paul Renton
Onu c ++ 11 olarak etiketledi. Ama nasıl oluyor da c ++ 11'de çalışmıyor? - Don Larynx


C ++ 0x'da bunun için bir kurucu oluşturabilirsiniz. Onunla hiçbir deneyimim yok, ama deniyor gibi görünüyor başlatıcı listesi-kurucu.

Bir kapsayıcı, böyle bir başlatıcı listesi kurucu uygulayabilir:

template<class E> class vector {
public:
    vector (std::initializer_list<E> s) // initializer-list constructor
    {
        reserve(s.size());  // get the right amount of space
        uninitialized_copy(s.begin(), s.end(), elem);   // initialize elements (in elem[0:s.size()))
        sz = s.size();  // set vector size
    }

    // ... as before ...
};

6
2017-11-07 14:05





Std :: initializer_list şablon tipini kullanmanız gerekir. Örnek:

#include <iostream>
class X {
    public:
        X (std::initializer_list<int> list) {
        for (auto i = list.begin(); i != list.end(); i++) {
                std::cout << *i << std::endl;
            }
        }
};


int main () {
    X x = {1,2,3,4,5};
}

3
2017-11-07 14:13