2010-07-29 2 views
11

저는 현재 가능한 한 많은 외부 의존성을 가져야하는 C++ 프로젝트에서 작업하고 있습니다. 따라서 STL과 부스트에 상당히 집착하고 있습니다. 지금까지 C++에 관해서는 거의 독점적으로 Qt-land에 살고있었습니다. 일반적으로 저는 C#과 Python을 사용할 수 있습니다.가독성을위한 STL 숙어를 감싸는 것이 좋습니다.

오늘 std::vector에 특정 항목이 있는지 확인하고 싶습니다. Qt를 사용하면 이렇게 할 수 있습니다.

QList<int> list; 
list.append(1); 
list.append(2); 
list.append(3); 

if (list.contains(2)) 
{ 
    // do something 
} 

멋지고 읽기 쉽습니다. 그러나 std::vector에는 contains 메서드가 없으므로 놀랍습니다. 좋아요. STL 관용구는 그런 무엇인가? 주위를 검색하면 다음과 같이 보입니다.

std::vector<int> list; 
list.push_back(1); 
list.push_back(2); 
list.push_back(3); 

std::vector<int>::const_iterator result = 
    std::find(list.begin(), list.end(), 2); 

if (result != list.end()) 
{ 
    // do something 
} 

저에게 (나에게는) 거의 읽을 수없고 너무 자세한 내용입니다. 그래서 나는 벡터와 값을 취하는 유틸리티 함수를 작성하고 그 값을 찾았는지 아닌지에 따라 bool을 반환한다는 것을 알게되었습니다. 기본적으로, 템플릿 화 된 메소드; 위의 std::find 호출에 대한 래퍼. 그런 다음 Qt 예제와 비슷한 방식으로 사용할 수 있습니다.

필자는 다른 이유로 인해 다른 STL 관용구를 감싸는 것이 아니라 가독성을 높이기 위해 몇 가지 유사한 유틸리티 기능을 염두에두고 있습니다. 내가 알고 싶은 건 ...이게 나쁜 생각이야? 다른 사람들도 똑같은 행동을합니까? 내가 뭔가 중요한 것을 놓친 건가? 이 코드는 한 시점에서 OSS가 될 것이며 다른 C++ 개발자가 이상하게 보일 수있는 이상한 것을하지는 않을 것입니다.

+1

@rgrig 제게는 여전히 Qt 예제처럼 읽기 쉽지 않습니다. 당신이 말했듯이 그렇게 효율적이지는 않습니다. O (n/2)가 아니고 O (n)이어야합니다. – Lucas

+0

O (n/2)가 O (n) 인 경우 분명히 삭제되었으므로 귀하가 추천하는 내용을 잘 모릅니다. 효율성 측면에서 볼 때, 그러한 래퍼는 콜 사이트에서 변경없이 세트/맵이 정렬되는 것을 이용하기 위해 오버로드 될 수 있습니다. –

답변

6

도움이 될 유틸리티 기능을 작성하는 데는 아무런 문제가 없으며 코드를보다 명확하게 만듭니다. 다른 사람들도 똑같이합니다. Boost library은 그러한 유틸리티 함수 및 클래스 중에서 가장 큰 집합입니다.

라이브러리는 C++ 프로그램에 의해 확장 될 수 있습니다 :

더는 C++ 표준이 명시 적으로 표준 라이브러리 (17.3.1.2/1)를 확장하기 위해 제안 말할 수 있습니다. 각 절은 해당 확장이 충족해야하는 요구 사항을 설명합니다.

  • 템플릿 인수
  • 파생 클래스
3

내가 말하고 싶지만 인터페이스 규칙을 충족

  • 컨테이너, 반복자 및/또는 알고리즘 : 이러한 확장은 일반적으로 다음 중 하나입니다 그것은 확실히 좋은 생각입니다. C++ STL에는 Python/C# 프로그래머가 표준 라이브러리에서 기대하는 많은 기능이 빠져 있습니다. 2-3 라인의 STL 접근 방식을 사용하여 코드를보다 쉽게 ​​읽을 수 있고 단일 기능으로 만들 수 있다면 계속 진행하십시오!

    다음은 매우 유사한 문제의 다른 예입니다. 종종 intstd::string으로 변환하려고합니다. 놀랍게도, STL을 사용하여이를 수행하는 간결한 방법은 없습니다. 그래서 stringstreamint을 넣고 그 결과로 string을 반환하는 데 필요한 2-3 줄을 실행하는 toStr 함수를 작성했습니다.

    편집 : 명확하게하기 위해 직접 작성하기 전에 boost 해결책을 찾아 보시기 바랍니다.나의 예는 STL의 한계를 보여주기위한 것이었지만, "STL이 빠진 것이 무엇이든, boost이 가지고있는 것"에 대한 대안적인 해석이있다.

  • +5

    boost 문자열을 스트리밍 할 수있는 문자열로 변환하는 lexical_cast <>()가 있습니다. –

    +2

    boost :: lexical_cast (str) 또한 역순으로 처리하고 문자열을 구문 분석하고 int를 반환합니다. – bradgonesurfing

    +0

    사실, 그게 내가 지금 사용하는 것입니다. 나는 단지 예를 든다. :) –

    9

    부스트가 훨씬 깔끔합니다. STL 반복기 기반 알고리즘을 더 이상 사용하지 않습니다. 범위 기반 알고리즘은 훨씬 깔끔한 추상화 이며 훨씬 더 깨끗한 코드가됩니다.

    #include <boost/range/algorithm/find.hpp> 
    
    void foo(){ 
        std::vector<int> list; 
        ... 
        ... 
        boost::find(list, 2) != list.end() 
    } 
    
    1

    필자의 현재 프로젝트에서는 contains()와 같은 몇 가지 메소드가 포함 된 stlutils.h 파일이 있습니다. 로 구현 :

    template<class Container, class T> 
    bool contains(const Container& c, const T& value) { 
        return std::find(c.begin(), c.end(), value) != c.end(); 
    } 
    

    가 더 많은 기능이 있습니다,하지만 난 당신이 다른 대답은 당신이 당신을 위해이 작업을 수행하는 유틸리티 함수를 작성할 수있는 지점을 만들었습니다

    1

    요점을 파악 생각하고, 그 좋은 생각 당신이 그것을 필요로하는 곳. 하지만 STL은 알고리즘 효율성을 중심으로 설계되었습니다. STL을 사용한 거의 모든 작업에는 표준 위임 된 big-O 효율성 요구 사항이 있습니다.

    vector의 멤버가 인 경우 벡터는 간단한 연속 목록이므로 호출하는 데 확실히 O (n)이됩니다. 또한 편리하기 때문에 대규모 데이터 세트에서도 정기적으로 사용하여 프로그래머가 알고리즘 성능이 좋지 않은 응용 프로그램의 디자인을 장려 할 수 있습니다. 의 경우 컨테이너가 특정 요소를 보유하고 있는지 확인하는 것이 중요 할 경우 모든 요소가 고유하다는 보장이 추가되어 O (log n) 효율성 조회를 사용하면 std::set이 거의 확실한 선택입니다. O (1)은 std::unordered_set입니다.

    내 개인적인 견해 : STL이 제공하는 모든 컨테이너와 기능을 배우면 간결하면서도보다 효율적인 프로그래밍 스타일을 찾을 수 있습니다. 당신이 뭔가를 놓친다면 질문에 묻습니다. 그렇습니다. 당신이 사용하는 용기에 대해 더 신중하게 생각하기를 원합니다. 요즘 정기적으로 vector 대신 set을 사용합니다.

    1

    나는 래퍼의 팬이 아니다. 그러나 그들이 당신을 도와 준다면, 그것을 가져라. 시간이 지남에 따라 std :: vector 외에도 다른 컨테이너에서 유틸리티 함수를 사용하고자 할 것입니다. 결국 유틸리티 함수는 매우 일반화되어 std :: find를 직접 사용할 수 있습니다.

    하지만 올바른 컨테이너를 사용하고 계십니까? std :: set에는 기본적으로 contains()와 동일한 count() 메서드가 있습니다. 그리고 O (n)보다는 O (log (n))입니다.

    관련 문제