Last active
August 29, 2015 14:19
-
-
Save goyusia/94e98708443bd64e7940 to your computer and use it in GitHub Desktop.
Calculate Average (C++ Template Metaprogramming)
This file contains hidden or 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 <type_traits> | |
| #include <cstdio> | |
| template<int... Items> | |
| struct intlist; | |
| template<typename intlist, int I> | |
| struct push_back; | |
| template<int I, int Head, int... Remainder> | |
| struct push_back<intlist<Head, Remainder...>, I> { | |
| typedef intlist<Head, Remainder..., I> value; | |
| }; | |
| template<int I> | |
| struct push_back<intlist<>, I> { | |
| typedef intlist<I> value; | |
| }; | |
| typedef push_back<intlist<>, 1>::value push_back_1; | |
| static_assert(std::is_same<push_back_1, intlist<1>>::value == 1, ""); | |
| typedef push_back<push_back_1, 2>::value push_back_2; | |
| static_assert(std::is_same<push_back_2, intlist<1, 2>>::value == 1, ""); | |
| template<typename intlist> | |
| struct length; | |
| template<int Head, int... Remainder> | |
| struct length< intlist<Head, Remainder...>> { | |
| enum { | |
| value = 1 + length<intlist<Remainder...>>::value | |
| }; | |
| }; | |
| template<> | |
| struct length < intlist<> > { | |
| enum { | |
| value = 0 | |
| }; | |
| }; | |
| static_assert(length<intlist<>>::value == 0, ""); | |
| static_assert(length<intlist<1>>::value == 1, ""); | |
| static_assert(length<intlist<1, 2>>::value == 2, ""); | |
| template<typename intlist> | |
| struct sum; | |
| template<int Head, int... Remainder> | |
| struct sum < intlist<Head, Remainder...> > { | |
| enum { | |
| value = Head + sum<intlist<Remainder...>>::value | |
| }; | |
| }; | |
| template<> | |
| struct sum < intlist<> > { | |
| enum { | |
| value = 0 | |
| }; | |
| }; | |
| static_assert(sum<intlist<>>::value == 0, ""); | |
| static_assert(sum<intlist<1>>::value == 1, ""); | |
| static_assert(sum<intlist<1, 2>>::value == 3, ""); | |
| template<int Number, int Size> | |
| struct divide { | |
| enum { | |
| value = Number / Size, | |
| remainder = Number % Size | |
| }; | |
| static float get_value() { | |
| float val = value + (float)(remainder) / Size; | |
| return val; | |
| } | |
| }; | |
| static_assert(divide<9, 4>::value == 2, ""); | |
| static_assert(divide<9, 4>::remainder == 1, ""); | |
| namespace AverageFunction { | |
| // 정수 리스트에 값을 집어넣은 다음 평균을 구하는 코드(?) | |
| typedef intlist<> empty; | |
| typedef push_back<empty, 1>::value list_1; | |
| typedef push_back<list_1, 2>::value list_2; | |
| typedef push_back<list_2, 4>::value list_3; | |
| typedef push_back<list_3, 8>::value list_4; | |
| typedef push_back<list_4, 16>::value target_list; | |
| const int list_size = length<target_list>::value; | |
| const int list_sum = sum<target_list>::value; | |
| const float retval = divide<list_sum, list_size>::get_value(); | |
| } | |
| int main() { | |
| printf("Average = %f\n", AverageFunction::retval); | |
| return 0; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment