[모던C++입문] 4.4 유틸리티

    4.4 유틸리티

    튜플

    • 새로운 클래스를 구현하지 않고 여러결과를 반환하기 위해 튜플(Tuple)을 사용
    • 대부분의 컨테이너와는 달리, 개체의 개수를 컴파일 타임에 알고 있어야 함
    void lu(const matrix& A, matrix& LU, vector& p) {...}
    
    tuple<matrix, vector> lu(const matrix& A)
    {
        matrix LU(A)
        vector p(n)
        ...
        //둘다 반환값은 동일
        return tuple<matrix, vector>(LU, p);    
        return make_tuple(LU, p);       //헬퍼 함수
    }
    
    int main()
    {
        tuple<matrix, vector> t = lu(A);
        //튜플의 값을 가져올때는 get함수를 통해 추출한다
        matrix LU = get<0>(t);
        vector p = get<1>(t);
    
        //모두 추론 가능하기에 위와 동일
        auto t = lu(A);
        auto LU = get<0>(t);
        auto p = get<1>(t);
    
        //튜플의 갯수보다 인덱스가크면 컴파일 오류 발생
        auto stupid = get<2>(t);
    
        //C++14에서는 항목의 타입이 명확할경우 타입별로 접근도 가능
        auto t = lu(A);
        auto LU = get<matrix>(t);
        auto p = get<vector>(t);
    
        //tie함수를 사용하여 튜플의 항목을 분리 가능
        matrix LU;
        vector p;
        tie(LU, p) = lu(A);
    }

    function

    • <functional> 헤더에 있는 클래스 템플릿 function은 일반화된 함수포인터 이다.
    double add(double x, double y)
    {
        return x + y;
    }
    
    int main()
    {
        using big_fun = function<double(double, double)>;
        big_fun f = &add;
        cout << "f(6, 3) = " << f(6,3) << endl;
    }
    
    //호환 가능함 함수 개체의 컨테이너를 만들수 있음
    vector<big_fun> functions;
    functions.push_back(&add);  //함수는 함수포인터로 붕괴되기에 & 연산자 생략가능
    
    //펑터도 저장 가능
    struct mult
    {
        double operator()(double x, double y) const { return x * y; }
    };
    functions.push_back(mult{});
    
    //하지만 클래스 템플릿은 타입이 아니기에 불가
    template<typename Value>
    struct power
    {
        Value operator(Value x, Value y) const { return pow(x,y); }
    };
    functions.push_back(power());   //오류
    functions.push_back(power<double>{});   //인스턴스화된 템플릿은 가능
    
    //함수 템플릿은 개체를 만들수 있음
    struct greater_t
    {
        template<typename Value>
        Value operator()(Value x, Value y) const { return x > y; }
    } greater_than;
    functions.push_back(greater_than);
    function<double(float, double)> ff = greater_than;  //인수타입이 달라 오류
    
    //람다를 function 개체로 저장 가능
    functions.push_back([](double x, double y) { return x / y; });
    
    //컨테이너의 각 항목은 함수처럼 호출 가능
    for( auto& f : functions)
        cout << "f(6.3) = " << f(6.3) << endl;

    레퍼런스 래퍼

    • 일반적으로 레퍼런스의 컨테이너를 만들 수 없다
    • C++11에서 reference_wrapper를 제공
    vector<vector<int>&> vv;    //오류
    
    vector<reference_wrapper<vector<int>>> vv;
    
    vector<int> v1 = {2,3,4}, v2 = {5,6,}, v3 = {7, 8};
    //reference_wrapper<T> 로 암시적 변환
    vv.push_back(v1);
    vv.push_back(v2);
    vv.push_back(v3);
    vv.push_back(v2);
    vv.push_back(v1);
    
    //get 메서드로 레퍼런스를 가져와 사용할 수 있다.
    for( const auto& vf : vv)
    {
        copy(begin(vr.get()), end(vr.get()), ostream_iterator<int>(cout, ", "));
        cout << endl;
    }
    반응형

    댓글

    Designed by JB FACTORY