반응형

가변인자 템플릿(Variadic template)를 활용하여 tuple 전체 요소를 출력

 

#include <iostream>
#include <tuple>
using namespace std;

//튜플과 index_sequence를 받아서 튜플 전체 요소를 출력
template<typename TP, size_t ... I> 
void print_tuple_imp(const TP& tp, const index_sequence<I...>&)
{
    int x[] = { get<I>(tp)... };

    for (auto& n : x)
        cout << n << ", ";
}

template<typename TP>
void print_tuple(const TP& tp)
{
    // 튜플 사이즈를 구해서 index_sequence를 생성하여 print_tuple_imp에 전달
    print_tuple_imp(tp, make_index_sequence<tuple_size<TP>::value>());
}

int main()
{
    tuple<int, int, int> tp(1, 2, 3);

    print_tuple(tp);
}
반응형

반응형

기반 클래스의 멤버에 접근하는 방법(기반 지식)

  • 기반 클래스의 멤버와 파생클래스의 멤버의 이름이 동일할때는 자신(파생 클래스)의 멤버가 우선

  • 기반 클래스의 멤버에 접근하는 방법

    • d.Base::value

    • static_cast<Base&>(d).value;

  • 값 캐스팅과 참조 캐스팅

    • static_cast<Base>(d): 임시객체 생성. lvalue가 될 수 없음

    • static_cast<Base&>(d): 임시객체를 생성 안함. lvalue가 될 수 있음

#include <iostream>
using namespace std;

struct Base
{
    int value = 10;
};

struct Derived : public Base
{
    int value = 20;
};

int main()
{
    Derived d;

    cout << d.value << endl; // 20
    cout << d.Base::value << endl; // 10

    cout << static_cast<Base>(d).value << endl; // 10 임시객체 생성
    cout << static_cast<Base&>(d).value << endl; // 10 참조

    //static_cast<Base>(d).value = 30; // Error
    static_cast<Base&>(d).value = 30; // OK

}

 

Tuple_element

  •  tuple이 가진 N번째 요소의 타입을 구하는 템플릿

  • 메인 템플릿(Main template) 생성, 구현은 불필요함으로 생략

  • 0번째 요소를 구하는 부분 특수화 구현

  • N번째 요소를 구하는 부분 특수화 구현(Recursive)

#include <iostream>
using namespace std;

// tuple 메인 템플릿
template<typename ... Types> struct xtuple
{
    static constexpr int N = 0;
};

// tuple 부분 특수화
template<typename T, typename ... Types> 
struct xtuple<T, Types...> : public xtuple<Types...> // 타입을 상속을 통해 재귀 저장 효과
{
    T value;
    xtuple() = default; // 기본 생성자
    xtuple(const T& v, const Types& ... args) 
        : value(v), xtuple<Types...>(args...) {} // Pack expansion으로 가변인자 전달

    static constexpr int N = xtuple<Types...>::N + 1;
};

// 메인 템플릿
template<size_t N, typename TP> struct xtuple_element;

// 요소의 타입을 구할 수 있도록 부분 특수화
template<typename T, typename... Types> struct xtuple_element<0, xtuple<T, Types...>>
{
    typedef T type;
    typedef xtuple<T, Types...> tupleType;
};

// 요소의 타입을 구할 수 있도록 부분 특수화
template<size_t N, typename T, typename... Types> 
struct xtuple_element<N, xtuple<T, Types...>>
{
    typedef typename xtuple_element<N-1, xtuple<Types...>>::type type;
    typedef typename xtuple_element<N-1, xtuple<Types...>>::tupleType tupleType;
};

// xtuple 요소를 꺼내는 함수
template<size_t N, typename TP>
typename xtuple_element<N, TP>::type& xget(TP& tp)
{
    return static_cast<typename xtuple_element<N, TP>::tupleType&>(tp).value;
}

int main()
{
    xtuple<int, double, char> t3(1, 3.4, 'A'); // 1
    
    cout << xget<1>(t3) << endl; // 3.4
    xget<1>(t3) = 1.1;
    cout << xget<1>(t3) << endl; // 1.1
}
반응형

반응형

tuple C++11 표준

  • 서로 다른 타입의 객체를 N개 보관하는 템플릿
#include <iostream>
#include <tuple>
using namespace std;

int main()
{
    tuple<> t0;
    tuple<int> t1(1);
    tuple<int, double, int, char> t4(1, 3.4, 2, 'A');

    get<2>(t4) = 15; // 참조 리턴으로 값 변경 가능

    cout << get<2>(t4) << endl; // 2
}

tuple 만들기

  • 가변인자 템플릿을 사용해서 메인 템플릿(Main template)을 만듬

  • 1개의 요소를 보관할 수 있도록 부분 특수화 구현

  • 상속을 사용해서 N개를 보관할 수 있게 구현

  • 생성자등 필요한 멤버 추가

#include <iostream>
using namespace std;

// tuple 메인 템플릿
template<typename ... Types> struct xtuple
{
    static constexpr int N = 0;
};

// tuple 부분 특수화
template<typename T, typename ... Types> 
struct xtuple<T, Types...> : public xtuple<Types...> // 타입을 상속을 통해 재귀 저장 효과
{
    T value;
    xtuple() = default; // 기본 생성자
    xtuple(const T& v, const Types& ... args) 
        : value(v), xtuple<Types...>(args...) {} // Pack expansion으로 가변인자 전달

    static constexpr int N = xtuple<Types...>::N + 1;
};

int main()
{
    xtuple<> t0;
    xtuple<int> t1(3);
    xtuple<int, double, char> t4(1, 3.4, 'A');
}
반응형

반응형

XTuple(Couple 선형화 구현)

  • Couple 재귀 호출 대신 선형 호출 할 수 있는 패턴 지원
    • Couple<int, Couple<int, double>...> -> XTuple<int, int, double...> 형태로 개선
  • Null 클래스 활용(Empty class)

    • 멤버 없는 클래스

    • 크기는 항상 1(sizeof(Null))

    • 멤버는 없지만 타입이므로 함수 오버로딩이나 템플릿 인자로 활용

  • 상속 활용 기술

  • 개수의 제한을 없앨 수 없을까? C+++ Variadic template

#include <iostream>
#include <type_traits>
using namespace std;

template<typename T, typename U> struct Couple
{
    T v1;
    U v2;

    enum { N = 2 };
};

// 빈 파라미터로 활용하기 위한 empty class
struct Null {};

// 2개이상 5개 미만의 타입전달
template<typename P1,
typename P2,
typename P3 = Null,
typename P4 = Null,
typename P5 = Null> 
class XTuple 
    : public Couple<P1, XTuple<P2, P3, P4, P5, Null>>
{

};

// XTuple 상속을 종료하기 위한 특수화
template<typename P1, typename P2>
class XTuple<P1, P2, Null, Null, Null>
    : public Couple<P1, P2>
{

};

int main()
{
    // Couple을 선형화하여 XTuple 형태로 사용
    XTuple<int, char, long, short, double> t5;
}
반응형

+ Recent posts