현재 구현에서 각각 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
이 좋아하는'표준 : tuple' 구현을 확인하십시오. – Xeo