2014-12-23 4 views
5

학습용 연습으로 저는 익숙한 argc와 argv 값을 main으로 관리하는 클래스를 만들고 있습니다. std :: strings의 argv를 std :: vector로 저장하고있다. 잠시 동안 나는 마치 마치 벡터 인 것처럼 내 객체를 반복하고 싶습니다. 내가 겪고있는 문제는 내 솔루션이 컨테이너의 선택에 크게 의존하게되고 컴파일러가 문제를 해결하려고 할 때 중단된다는 것입니다. 관찰 :자동 유형에서 자동 방법으로 실패합니다. 왜?

이 예제에서는이 클래스를 사용하고 싶습니다.

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

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

이것은 매우 사소하지만 연구가 필요했습니다. 내 헤더 파일은 다음과 같습니다

typedef char* cstring; 

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

    std::vector<std::string>::const_iterator begin(); 
    std::vector<std::string>::const_iterator end(); 
}; 

및 CLI 클래스의 소스 파일이 여기에 있습니다. (빼기 등 포함)

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(); 
} 

이것은 훌륭하게 작동하지만 여기에 내 첫 번째 문제가 있습니다. 벡터 대신 링크 된 목록을 사용하기로 결정했다면 이제 클라이언트 코드가 어리석은 날에 루프를 위해 자동을 사용하지 않는다면 적어도 변경해야하는 부분이 5 개 이상 있습니다. 그렇지 않은 경우). 이것은 자동 구출의 경우가되어야하는 것처럼 느껴집니다! 새로운 C의 ++ 기능으로 나는이에 메소드 서명을 변경 할 수 있어야한다 :

.../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’ 

좋아요 : 내가 마지막으로 오류가 발생하는 경우

... // Header 
auto begin(); 

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

이입니다. 이것이 무엇을 의미하는지 추측해야한다면 for 루프의 auto가 begin 메서드의 서명을 찾고 있다고 가정하여 구체적인 반환 유형을 찾고자합니다. 그 대신 자동차와 패닉이 있습니다.

이 이론은 정확하며 이터레이터에도 불구하고 컨테이너 유형을 숨기는 더 좋은 방법이 있습니까?

P. 이 문제를 좀더 자세히 살펴볼수록이 기능은 어쨌든 최종 제품에서 원하는 기능이 아님을 깨닫고 있습니다. 그러나 이것은 여전히 ​​뭔가를 배우는 기회처럼 보입니다.

+1

단순히'std :: vector 옵션 (int argc, const char * const * argv) {return {argv, argv + argc}; }'? – Casey

+0

앞으로이 클래스를 사용하여 옵션을 내부적으로 파싱 할 수 있기를 바랍니다. 그런 식으로 외부 옵션을 검색하는 대신 각 옵션에 대해 'bool'메소드를 사용할 수 있습니다. – Jwashton

답변

2

헤더 코드를 포함하지 않기 때문에, MAIN.CPP의 컴파일 단위 이것은 당신이하려는 것에 대해 더 잘 작동 할 begin()

에 대한 auto의 의미를 추론 할 수 없습니다

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;                
} 

CONST 안전에 대한 참고 : "const_iterator를가"반드시 자체에서 const 있지만 나타내는 객체가 CONST임을되지 않는 고유 한 유형임을 기억하십시오. 즉, 타입이 다르므로 a.begin()을 const 함수 내에 반환 할 수 없습니다.순진한 사람은 const decltype(a.begin()) 반환 유형을 추가하려고 시도 할 수 있지만 여전히 vector::const_iterator이 아니며 const vector::iterator입니다.

+0

아! 고맙습니다! 재미있는 잡기. 아마도 이러한 작은 방법을 인라인하여 문제를 해결할 수있을 것입니다. 또 다른 생각, 반환 형식 후위를 포함하도록 메서드 선언을 변경할 수 있습니까? 'auto begin() -> decltype (arguments.begin());'이번에도 노력할 가치는 없지만 알아두면 좋을 것입니다. – Jwashton

+1

왜 auto 대신 decltype을 사용하지 않는 것이 좋을까요? – inetknght

+0

완벽! 나는 심지어 내가 const_iterator를 얻도록'begin()'대신에'cbegin()'을 호출 할 수 있음을 발견했다. 모든 곳에서 같은 결과가 나타납니다. 고맙습니다! =) – Jwashton