2016-01-06 11 views
10

Napisałem niestandardową klasę kontenera, która zawiera instancję std::vector<double> - działa ładnie. W celu zapewnienia zgodności z innymi interfejsami API chciałbym wyeksportować zawartość kontenera jako kopię std::vector<double>. Obecnie to działa:C++ - utwórz nowy konstruktor dla std :: vector <double>?

MyContainer container; 
.... 
std::vector<double> vc(container.begin(), container.end()); 

Ale jeśli to możliwe, chciałaby, aby móc napisać:

MyContainer container; 
.... 
std::vector<double> vc(container); 

mogę (łatwo) stworzyć taki std::vector<double> konstruktora?

+0

Dziękuję za wszystkie sugestie; Dowiedziałem się o "operatorze obsady" - dzisiaj; jednak generalnie wolę wyraźne implicite, więc przyjąłem odpowiedź z @Madame Elyse – user422005

+0

Pomimo tego, co mówią odpowiedzi, nie ma czegoś takiego jak "operator obsady". Mówią o "operator ** konwersji", którego zadaniem jest po prostu zapewnić konwersję z jednego rodzaju na inny. ** ** cast to coś, co piszesz w swoim kodzie, aby powiedzieć kompilatorowi, aby zrobił konwersję. To ** wyraźna ** konwersja. Kompilator może również wykonywać niektóre konwersje bez wyświetlania rzutowania. To ** niejawna ** konwersja. Kiedy oznaczysz operatora konwersji jako "jawny", ograniczysz okoliczności, w których kompilator może go użyć, a często kończy się to wymaganiem obsady. –

Odpowiedz

17

Można stworzyć wyraźną przemianę std::vector<double>:

explicit operator std::vector<double>() const { 
    return std::vector<double>(begin(), end()); 
} 

Następnie std::vector<double> vc(container); wywoła konstruktor std::vector<double> ruch.

Należy pamiętać, że konwersje, które są kosztowne pod względem obliczeniowym, są generalnie mile widziane. Dlatego funkcja fabryka wektor może być mądrzejszy podejście:

class MyContainer { 
public: 
    using value_type = double; 
    // ... 
}; 

template<typename Source> 
auto to_vector(Source source) { 
    return std::vector<typename Source::value_type>(source.begin(), source.end()); 
} 

Potem piszesz:

MyContainer container; 
// ... 
auto vc = to_vector(container); 

Jest również bardziej ogólne, jak to działa z czymkolwiek, który ma zgodną value_type, begin i end członków.

2

Czy mogę (łatwo) utworzyć takiego konstruktora std :: vector?

Nie można, ponieważ wymagałoby to zmiany deklaracji klasy std::vector.

Możesz jednak podać operatora obsady dla MyContainer na std::vector<double>.

1

Nie możesz i nie powinieneś zmienić API klasy, której sam nie napisałeś. Ale myślę, że w twoim przypadku operator odlewania zrobiłby dobrze. Na przykład (ten potrzebuje -std=c++11):

#include <iostream> 
#include <vector> 

struct Foo 
{ 
    operator std::vector<double>() const 
    { 
    return std::vector<double> { 1, 2, 3 }; 
    } 
}; 

int main() 
{ 
    Foo foo; 
    std::vector<double> bar = foo; // Applies the cast operator defined in Foo 
    std::cout << bar.size() << std::endl; // Prints "3" 
    return 0; 
} 
+0

Źle i źle! Zrób to "explicite", przynajmniej .... –

+1

Czy możesz wyjaśnić, dlaczego jest źle i dlaczego jest nie tak? – mindriot

+0

Dobrze zakodowane w innych odpowiedziach i komentarzach. Ciężkie niejawne konwersje, takie jak te, powodują błędy. –

Powiązane problemy