2014-12-23 20 views
5

Jako ćwiczenie edukacyjne buduję klasę do zarządzania starymi znanymi wartościami argc i argv do main. Przechowywuję argv jako std :: vector std :: string. Na razie chciałbym zapętlić się nad moim obiektem, jak gdyby był to wektor. Problem, który mam, polega na tym, że moje rozwiązanie staje się wysoce zależne od mojego wyboru kontenera i kompilator ulega przerwaniu, gdy próbuję go naprawić. Obserwuj:Automatyczny typ do metody automatycznej kończy się niepowodzeniem. Czemu?

W ten sposób chciałbym, aby moja klasa pracowała dla tego przykładu.

int main(int argc, char* argv) { 
    CLI options(argc, argv); 

    for (auto option : options) { 
    cout << option << endl; 
    } 
} 

Jest to dość trywialne, ale wymagało to momentu badań. Oto mój plik nagłówkowy

i mój plik źródłowy dla klasy CLI. (minus zawiera itd.)

CLI::CLI(const int argc, const cstring argv[]) { 
    arguments = std::vector<std::string>(argv, argv + argc); 
} 

std::vector<std::string>::const_iterator CLI::begin() { 
    return arguments.begin(); 
} 

std::vector<std::string>::const_iterator CLI::end() { 
    return arguments.end(); 
} 

To działa pięknie, ale tutaj jest mój pierwszy problem. Jeśli zdecyduję, że chcę użyć połączonej listy zamiast wektora, mam teraz co najmniej pięć punktów, które muszą się zmienić, więcej, jeśli mój kod klienta ma głupi dzień i nie używa automatycznie dla swojej pętli (lub cokolwiek innego inaczej to robi). Wydaje się, że powinno to być auto-to-the-rescue! Dzięki nowym funkcjom C++ powinien być w stanie zmienić podpis metody to:

... // Header 
auto begin(); 

... // Source 
// Possibly without the decltype now? Not sure how or when... 
auto CLI::begin() -> decltype(arguments.begin()) { 
    return arguments.begin(); 
} 

To gdzie w końcu pojawia się błąd:

.../main.cpp: In function ‘int main(int, char**)’: 
.../main.cpp:10:22: error: use of ‘auto CLI::begin()’ before deduction of ‘auto’ 
    for (auto option : options) { 
        ^
.../main.cpp:10:22: error: invalid use of ‘auto’ 

porządku. Gdybym miał zgadywać, co to oznacza, powiedziałbym, że auto w pętli for szuka podpisu dla metody początku, mając nadzieję znaleźć konkretny typ zwrotu. Zamiast tego znajdzie się auto i panika.

Czy ta teoria jest poprawna i czy istnieje lepszy sposób na ukrycie kontenera pomimo iteratorów?

P.S. Im więcej patrzę na ten problem, tym bardziej zdaję sobie sprawę, że ta funkcja prawdopodobnie nie jest funkcją, jaką chcę w końcowym produkcie. Ale wciąż wydaje się, że można się czegoś nauczyć.

+1

Dlaczego nie po prostu opcje 'std :: vector (int argc, const char * const * argv) {return {argv, argv + argc}; } '? – Casey

+0

Ponieważ w przyszłości chciałbym móc korzystać z tej klasy, aby analizować opcje wewnętrznie. W ten sposób mogłem zastosować metody 'bool' dla każdej opcji zamiast szukać ich na zewnątrz. – Jwashton

Odpowiedz

2

Ponieważ nagłówek nie zawiera kodu, urządzenie kompilacja dla main.cpp nie można wywnioskować znaczenie auto dla begin()

Byłoby lepiej dla tego, co zamierzamy:

header.h

#include <vector>                 

class A { 
public: 
     std::vector<int> a; 
     decltype(a.begin()) begin(); 
     decltype(a.cbegin()) cbegin() const; 
}; 

Header.cpp

#include "header.h" 
decltype(A::a.begin()) A::begin() { 
     return a.begin(); 
} 
decltype(A::a.cbegin()) A::cbegin() const { 
     return a.cbegin(); 
} 

main.cpp

#include "header.h" 
int main(int argc, char **argv) { 
     A a; 
     auto b = a.begin(); 
     auto cb = a.cbegin(); 
     return 0;                
} 

Uwaga na bezpieczeństwo const: pamiętaj, że „const_iterator” to unikatowy typ, który niekoniecznie jest const się jednak, że obiekt reprezentuje jest const. Oznacza to, że typ jest inny, co zapobiega zwrocie a.begin() wewnątrz funkcji stałej.Naiwna może spróbować dodać typ zwracany const decltype(a.begin()), ale to wciąż nie jest vector::const_iterator, ale raczej const vector::iterator.

+0

Ah! Dziękuję Ci! Interesujący połów. Przypuszczalnie wprowadzenie tych małych metod rozwiązałoby problem. Kolejna myśl, czy mogę zmienić deklarację metody, aby dołączyć postfix typu powrotu? 'auto begin() -> decltype (arguments.begin());' Ponownie, prawdopodobnie nie jest to warte wysiłku, ale dobrze wiedzieć. – Jwashton

+1

Dlaczego po prostu nie ma decltype zamiast auto? – inetknght

+0

Idealny! Odkryłem nawet, że mogę wywołać 'cbegin()' zamiast 'begin()', aby nadal otrzymywać const_iterator. Ten sam wynik dookoła. Dziękuję Ci! =) – Jwashton

Powiązane problemy