Last active
August 29, 2015 14:14
-
-
Save leafbird/969d161c22c68dc78a59 to your computer and use it in GitHub Desktop.
Typelist: Implemented by variadic templates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "TypeList.h" | |
// from : https://functionalcpp.wordpress.com/2013/08/05/function-traits/ | |
template<class F> | |
struct function_traits; | |
// function pointer | |
template<class R, class... Args> | |
struct function_traits<R(*)(Args...)> : public function_traits<R(Args...)> { | |
}; | |
// member function pointer | |
template<class C, class R, class... Args> | |
struct function_traits<R(C::*)(Args...)> : public function_traits<R(C&, Args...)> | |
{}; | |
// const member function pointer | |
template<class C, class R, class... Args> | |
struct function_traits<R(C::*)(Args...) const> : public function_traits<R(C&, Args...)> | |
{}; | |
// member object pointer | |
template<class C, class R> | |
struct function_traits<R(C::*)> : public function_traits<R(C&)> | |
{}; | |
template<class R, class... Args> | |
struct function_traits<R(Args...)> { | |
using return_type = R; | |
using arg_types = TypeList::Types < Args... >; | |
static const size_t arity = TypeList::SizeOf<arg_types>::kValue; | |
template<size_t index> | |
struct argument { | |
using type = typename TypeList::TypeAt<arg_types, index>::Type; | |
}; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include "TypeList.h" | |
struct TypeA { int value = 10; }; | |
struct TypeB { int value = 20; }; | |
struct TypeC { int value = 30; }; | |
template<typename T> | |
struct Job { | |
static void Execute() { | |
std::cout << "sizeof(T) : " << sizeof(T) << std::endl; | |
} | |
}; | |
void main() { | |
using list = TypeList::Types<TypeA, TypeB>; | |
std::cout << TypeList::SizeOf<list>::kValue<< std::endl; | |
static_assert(std::is_same<TypeList::HeadOf<list>::Type, TypeA>::value, "error"); | |
static_assert(std::is_same<TypeList::TailOf<list>::Type, TypeB>::value, "error"); | |
std::cout << TypeList::IndexOf<list, TypeA>::kValue << std::endl; | |
std::cout << TypeList::IndexOf<list, TypeB>::kValue << std::endl; | |
//std::cout << TypeList::IndexOf<list, float>::kValue << std::endl; | |
TypeList::NextOf<list, TypeA>::Type d = TypeB(); | |
//TypeList::NextOf<list, char>::Type d = false; | |
std::cout << TypeList::IsElementOf<list, TypeB>::kValue << ", " | |
<< TypeList::IsElementOf<list, int>::kValue << std::endl; | |
using append_list = TypeList::Append < list, TypeC >::Type; | |
static_assert(TypeList::SizeOf<append_list>::kValue == 3, "error"); | |
static_assert(TypeList::IndexOf<append_list, TypeA>::kValue == 0, "error"); | |
static_assert(TypeList::IndexOf<append_list, TypeB>::kValue == 1, "error"); | |
static_assert(TypeList::IndexOf<append_list, TypeC>::kValue == 2, "error"); | |
static_assert(TypeList::IsElementOf<append_list, TypeC>::kValue, "error"); | |
static_assert(!TypeList::IsElementOf<list, TypeC>::kValue, "error"); | |
using removed_list = TypeList::Erase<append_list, TypeB>::Type; | |
static_assert(TypeList::SizeOf<removed_list>::kValue == 2, "error"); | |
static_assert(std::is_same<TypeList::HeadOf<removed_list>::Type, TypeA>::value, "error"); | |
static_assert(std::is_same<TypeList::TailOf<removed_list>::Type, TypeC>::value, "error"); | |
using merge_list = TypeList::Append<append_list, removed_list>::Type; | |
static_assert(TypeList::SizeOf<merge_list>::kValue == 5, "error"); | |
using test_types = TypeList::Types < int, short, char > ; | |
TypeList::Visitor<test_types, Job>::Execute(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace TypeList { | |
struct Null {}; | |
template<typename ...T> | |
struct Types; | |
template<typename _Head> | |
struct Types < _Head > { | |
using Type = Types < _Head > ; | |
using Next = Null; | |
using Current = _Head; | |
}; | |
template<typename _Head, typename ... _Tail> | |
struct Types < _Head, _Tail... > { | |
using Type = Types < _Head, _Tail... > ; | |
using Next = typename Types < _Tail... > ; | |
using Current = _Head; | |
}; | |
template<typename _Types> | |
struct SizeOf { | |
static const size_t kValue = 1 + SizeOf<_Types::Next>::kValue; | |
}; | |
template<> | |
struct SizeOf < Null > { | |
static const size_t kValue = 0U; | |
}; | |
template<typename _Types> | |
struct HeadOf { | |
using Type = typename _Types::Current; | |
}; | |
template<> | |
struct HeadOf < Null > { | |
using Type = Null; | |
}; | |
template<typename _Types> | |
struct TailOf { | |
using Type = typename TailOf<typename _Types::Next>::Type; | |
}; | |
template<typename _Tail> | |
struct TailOf < Types<_Tail> > { | |
using Type = _Tail; | |
}; | |
template<typename _Types, size_t _index> | |
struct TypeAt { | |
using Type = typename TypeAt<typename _Types::Next, _index - 1>::Type; | |
}; | |
template<typename _Types> | |
struct TypeAt < _Types, 0 > { | |
using Type = typename _Types::Current; | |
}; | |
template<typename _Types, typename _Type> | |
struct IndexOf { | |
static_assert(SizeOf<typename _Types::Next>::kValue != 0, "No such types in typelist"); | |
static const size_t kValue = typename IndexOf<typename _Types::Next, _Type>::kValue + 1U; | |
}; | |
template<typename _Types> | |
struct IndexOf <_Types, typename _Types::Current> { | |
static const size_t kValue = 0U; | |
}; | |
template<typename _Types, typename _Type> | |
struct NextOf { | |
using Type = typename NextOf<typename _Types::Next, _Type>::Type; | |
}; | |
template<typename _Types> | |
struct NextOf < _Types, typename _Types::Current > { | |
using Type = typename HeadOf<typename _Types::Next>::Type; | |
}; | |
template<typename _Types, typename _Type> | |
struct IsElementOf { | |
static const bool kValue = typename IsElementOf<typename _Types::Next, _Type>::kValue; | |
}; | |
template<typename _Types> | |
struct IsElementOf < _Types, typename _Types::Current > { | |
static const bool kValue = true; | |
}; | |
template<typename _Type> | |
struct IsElementOf < Null, _Type > { | |
static const bool kValue = false; | |
}; | |
template<typename _Types, typename ..._Type> | |
struct Append; | |
template<typename ..._Type1, typename ..._Type2> | |
struct Append < Types<_Type1...>, _Type2...> { | |
using Type = typename Types<_Type1..., _Type2...>::Type; | |
}; | |
template<typename ..._Type1, typename ..._Type2> | |
struct Append < Types<_Type1...>, Types<_Type2...>> { | |
using Type = typename Types<_Type1..., _Type2...>::Type; | |
}; | |
template<typename _Types, typename ... _Type> | |
struct PushFront; | |
template<typename ..._Type1, typename ..._Type2> | |
struct PushFront < Types<_Type1...>, _Type2... > { | |
using Type = typename Types<_Type2..., _Type1...>::Type; | |
}; | |
template<typename _Types, typename _Type> | |
struct Erase { | |
using Type = typename PushFront<typename Erase<typename _Types::Next, _Type>::Type, | |
typename _Types::Current>::Type; | |
}; | |
template<typename _Types> | |
struct Erase < _Types, typename _Types::Current > { | |
using Type = typename _Types::Next; | |
}; | |
template <typename _Types, template <class> class _Delegator> | |
struct Visitor { | |
static void Execute() { | |
_Delegator<typename _Types::Current>::Execute(); | |
Visitor<typename _Types::Next, _Delegator>::Execute(); | |
} | |
}; | |
template <template <class> class _Delegator> | |
struct Visitor<Null, _Delegator> { | |
static void Execute() {} | |
}; | |
} // namespace TypeList |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment