2014-09-17 3 views
1
template<typename... Types> 
struct Foo; 

template<typename T , typename... Types> 
struct Foo<T, Types ...> : public Foo<Types ...> 
{ 
    Foo(T member , Types ... others) : Foo<Types ...>(others...), m_member(member) 
    { 
    } 

    T m_member; 
}; 

template<typename T> 
struct Foo<T> 
{ 
    Foo(T member) : m_member(member) 
    { 
    } 

    T m_member; 
}; 

int main() 
{ 
    Foo<char,int,bool,double> f('a' , 42 , true , 1.234); 
} 

내가 어딘가에이 코드를 발견했는데 완전히 쓸모가 있는지 궁금한가요? 모든 회원은 m_member라고 불리는데 어떻게 접근 할 수 있습니까?가변 멤버를 액세스하려면 어떻게해야합니까?

cout << f.m_member;을 인쇄하면 'a'가 인쇄되지만 다른 회원은 액세스 할 수 없습니다.

+3

이 좋아하는'표준 : tuple' 구현을 확인하십시오. – Xeo

답변

2

현재 구현에서 각각 Foo 클래스의 부모 클래스는 m_member입니다. 인덱싱, 유형, 기타를 통해 각 필드에 액세스하는 논리를 구현하는 방법은 사용자에게 달려 있습니다.

하나의 가능성 (편의상 반대) 타입 또는 인덱스를 가지고 과부하 주형 멤버 함수에 액세스하는 것이다

#include <type_traits> 
#include <cstddef> 

template <typename... Types> 
struct Foo; 

template <typename T, typename... Types> 
struct Foo<T, Types...> : Foo<Types...> 
{ 
    // bring get() member functions from parent class into current scope 
    using Foo<Types...>::get; 

    Foo(T member, Types... others) : Foo<Types...>{others...}, m_member{member} {} 

    template <typename U> 
    auto get(T* = nullptr) 
     -> typename std::enable_if<std::is_same<U, T>::value, T&>::type 
    { 
     return m_member; 
    } 

    template <std::size_t N> 
    auto get(T* = nullptr) 
     -> typename std::enable_if<N == sizeof...(Types), T&>::type 
    { 
     return m_member; 
    } 

private: 
    T m_member; 
}; 

template <typename T> 
struct Foo<T> 
{ 
    Foo(T member) : m_member{member} {} 

    template <typename U> 
    auto get(T* = nullptr) 
     -> typename std::enable_if<std::is_same<U, T>::value, T&>::type 
    { 
     return m_member; 
    } 

    template <std::size_t N> 
    auto get(T* = nullptr) 
     -> typename std::enable_if<N == 0, T&>::type 
    { 
     return m_member; 
    } 

private: 
    T m_member; 
}; 

테스트 :

Foo<char, int, bool, double> a{ 'a', 42, true, 1.234 }; 

assert('a' == a.get<char>()); 
assert(42 == a.get<int>()); 

assert(true == a.get<1>()); 
assert(42 == a.get<2>()); 

a.get<char>() = 'b'; 
assert('b' == a.get<3>()); 

DEMO

들어 멤버에 대한 액세스를 제공하는 다른 구현은 인 std::tuple<...>을 참조하십시오.

정규 구현은 다음과 같습니다

#include <type_traits> 
#include <cstddef> 

template <typename... Types> 
struct Foo; 

template <typename T, typename... Types> 
struct Foo<T, Types...> : Foo<Types...> 
{ 
    Foo(T member, Types... others) : Foo<Types...>{others...}, m_member{member} {} 
    T m_member; 
}; 

template <typename T> 
struct Foo<T> 
{ 
    Foo(T member) : m_member{member} {} 
    T m_member; 
}; 

template <std::size_t N, typename T> 
struct element; 

template <typename T, typename... Types> 
struct element<0, Foo<T, Types...>> 
{ 
    using type = T; 
}; 

template <std::size_t N, typename T, typename... Types> 
struct element<N, Foo<T, Types...>> 
{ 
    using type = typename element<N - 1, Foo<Types...>>::type; 
}; 

template <std::size_t N, typename T, typename... Types> 
auto get(Foo<T, Types...>& f) 
    -> typename std::enable_if<N == 0, T&>::type 
{ 
    return f.m_member; 
} 

template <std::size_t N, typename T, typename... Types> 
auto get(Foo<T, Types...>& f) 
    -> typename std::enable_if<N != 0 
           , typename element<N, Foo<T, Types...>>::type& 
           >::type 
{ 
    Foo<Types...>& p = f; 
    return get<N - 1>(p); 
} 

template <typename U, typename T, typename... Types> 
auto get(Foo<T, Types...>& f) 
    -> typename std::enable_if<std::is_same<T, U>::value, T&>::type 
{ 
    return f.m_member; 
} 

template <typename U, typename T, typename... Types> 
auto get(Foo<T, Types...>& f) 
    -> typename std::enable_if<!std::is_same<T, U>::value, U&>::type 
{ 
    Foo<Types...>& p = f; 
    return get<U>(p); 
} 

테스트 :

Foo<char, int, bool, double> a{ 'a', 42, true, 1.234 }; 

assert(true == get<2>(a)); 
assert(42 == get<int>(a)); 

get<char>(a) = 'b'; 
assert('b' == get<0>(a)); 

DEMO 2

+0

'Foo '에서 어떻게 작동합니까? –

+0

@ BЈовић : 대부분의 파생 된 구현 (모든 args 포함)은 부모를 쉐이드하므로'get ()'으로 액세스하면 ctor의 첫 번째 인수가 반환됩니다 –

관련 문제