Created
December 2, 2013 15:11
-
-
Save quartorz/7750933 to your computer and use it in GitHub Desktop.
複数の関数オブジェクトを1つにまとめる ref: http://qiita.com/quartorz/items/0670b5e4aa63a76def1e
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 <iostream> | |
#include <tuple> | |
#include <string> | |
template <std::size_t... Indices> | |
class sequence{ | |
public: | |
using type = sequence<Indices...>; | |
}; | |
template <class, class> | |
class concat_impl; | |
template <std::size_t... Left, std::size_t... Right> | |
class concat_impl<sequence<Left...>, sequence<Right...>>: public sequence<Left..., Right...> | |
{ | |
}; | |
template <class Left, class Right> | |
using concat = typename concat_impl<Left, Right>::type; | |
template <class, std::size_t> | |
class shift_impl; | |
template <std::size_t N, std::size_t... Indices> | |
class shift_impl<sequence<Indices...>, N>: public sequence<(Indices + N)...> | |
{ | |
}; | |
template <class Sequence, std::size_t N> | |
using shift = typename shift_impl<Sequence, N>::type; | |
template <std::size_t Begin, std::size_t End> | |
class make_sequence_impl: | |
public shift< concat< | |
typename make_sequence_impl<0, (End - Begin) / 2>::type, | |
shift<typename make_sequence_impl<0, (End - Begin) / 2 + (End - Begin) % 2>::type, (End - Begin) / 2> | |
>, Begin> | |
{ | |
}; | |
template <> | |
class make_sequence_impl<0, 1>: public sequence<0> | |
{ | |
}; | |
template <> | |
class make_sequence_impl<0, 0>: public sequence<> | |
{ | |
}; | |
template <std::size_t Begin, std::size_t End> | |
using make_sequence = typename make_sequence_impl<Begin, End>::type; | |
template <class... Functions> | |
class caller{ | |
std::tuple<Functions...> functions; | |
template <std::size_t Head, std::size_t... Tail, class... Args> | |
void call_impl(sequence<Head, Tail...>, Args... args) | |
{ | |
std::get<Head>(functions)(args...); | |
call_impl(sequence<Tail...>(), args...); | |
} | |
template <class... Args> | |
void call_impl(sequence<>, Args...) | |
{ | |
} | |
public: | |
caller(Functions... funcs): functions(funcs...) | |
{ | |
} | |
template <class... Args> | |
void operator()(Args... args) | |
{ | |
call_impl(make_sequence<0, sizeof...(Functions)>(), args...); | |
} | |
}; | |
template <class... Functions> | |
caller<Functions...> make_caller(Functions... funcs) | |
{ | |
return caller<Functions...>(funcs...); | |
} | |
void function(const char *s, int a, int b) | |
{ | |
std::cout << "void function(const char *, int, int): " << s << ' ' << a << ' ' << b << std::endl; | |
} | |
class Class1{ | |
public: | |
void operator()(std::string s, int a, int b) | |
{ | |
std::cout << "Class1::operator()(): " << s << ' ' << a << ' ' << b << std::endl; | |
} | |
}; | |
class Class2{ | |
public: | |
template <class Type> | |
void operator()(Type s, int a, int b) | |
{ | |
std::cout << "Class2::operator()(): " << s << ' ' << a << ' ' << b << std::endl; | |
} | |
}; | |
int main() | |
{ | |
make_caller()(); | |
auto caller = make_caller([](const char *s, int a, ...){ | |
std::cout << "first lambda function: " << s << ' ' << a << std::endl; | |
}, [](const char *s, int a, int b){ | |
std::cout << "second second function: " << s << ' ' << a << ' ' << b << std::endl; | |
}, function, Class1(), Class2()); | |
caller("string1", 0, 1); | |
std::cout << std::endl; | |
caller("string2", 2, 3); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment