Skip to content

Instantly share code, notes, and snippets.

@hjanetzek
Last active August 29, 2015 14:25
Show Gist options
  • Save hjanetzek/ae30cf83023c8a926d1c to your computer and use it in GitHub Desktop.
Save hjanetzek/ae30cf83023c8a926d1c to your computer and use it in GitHub Desktop.
/*
clang++-3.6 -DVARIADIC_WRAPPER -O3 -Wall -Wpedantic -std=c++11 variadic.cpp
./a.out
objdump -j .rodata -j .text -d -S a.out > a.txt
clang++-3.6 -O3 -Wall -Wpedantic -std=c++11 variadic.cpp
./a.out
objdump -j .rodata -j .text -d -S a.out > b.txt
meld a.txt b.txt
g++ -DVARIADIC_WRAPPER -O3 -Wall -Wpedantic -std=c++11 variadic.cpp
./a.out
objdump -j .rodata -j .text -d -S a.out > a2.txt
g++ -O3 -Wall -Wpedantic -std=c++11 variadic.cpp
./a.out
objdump -j .rodata -j .text -d -S a.out > b2.txt
meld a2.txt b2.txt
*/
#include <tuple>
#include <iostream>
#include <functional>
//#define VARIADIC_WRAPPER 1
//#define NO_INLINE
#define NO_INLINE __attribute__((noinline))
#ifdef VARIADIC_WRAPPER
NO_INLINE void foo(int x, int y) {
std::cout << "A" << x << ":" << y << std::endl;
}
template<int ...>
struct seq {};
template<int N, int ...S>
struct gens : gens<N-1, N-1, S...> {};
template<int ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};
template <typename F, F f, typename ...Args>
struct State {
using Type = std::tuple<Args...>;
Type params;
NO_INLINE void operator()(Args... _param) {
auto _params = std::make_tuple(_param...);
if (_params != params) {
params = _params;
call(typename gens<sizeof...(Args)>::type());
}
}
template<int ...S>
void call(seq<S...>) {
f(std::get<S>(params) ...);
}
};
int main(void) {
State<decltype((foo)), foo, int, int> state;
state(1,2);
state(1,2);
state(2,2);
}
#else
NO_INLINE void baz(int x, int y) {
std::cout << "B" << x << ":" << y << std::endl;
}
template <typename T>
class State {
public:
void init(const typename T::Type& _default) {
T::set(_default);
m_current = _default;
}
NO_INLINE void operator()(const typename T::Type& _value) {
if (m_current != _value) {
m_current = _value;
T::set(m_current);
}
}
private:
typename T::Type m_current;
};
struct Test {
struct Type {
int x; int y;
bool operator!=(const Type& _other) { return x != _other.x || y != _other.y;}
};
inline static void set(const Type& _type) {
baz(_type.x, _type.y);
}
};
int main(void) {
State<Test> state;
state({1,2});
state({1,2});
state({2,2});
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment