Skip to content

Instantly share code, notes, and snippets.

@quartorz
Created December 2, 2013 15:11
Show Gist options
  • Save quartorz/7750933 to your computer and use it in GitHub Desktop.
Save quartorz/7750933 to your computer and use it in GitHub Desktop.
複数の関数オブジェクトを1つにまとめる ref: http://qiita.com/quartorz/items/0670b5e4aa63a76def1e
#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