Last active
May 28, 2017 03:30
-
-
Save NeuroWhAI/01f14be9aeacffaffb7298c3677fd7d4 to your computer and use it in GitHub Desktop.
Parameters like Member variables
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 <memory> | |
#include <functional> | |
#include <type_traits> | |
#include <tuple> | |
#include <utility> | |
template <typename... ARGS> | |
class Action | |
{ | |
private: | |
template <typename T> | |
using OrgT = std::remove_reference_t<T>; | |
public: | |
Action(std::function<void(ARGS...)> func) | |
: m_func(func) | |
, m_args(std::make_shared<OrgT<ARGS>>()...) | |
{ | |
m_packed = pack(func); | |
} | |
Action(const Action& other) | |
: m_func(other.m_func) | |
, m_args(std::make_shared<OrgT<ARGS>>()...) | |
{ | |
copyArguments(other.m_args); | |
m_packed = pack(other.m_func); | |
} | |
Action(Action&& other) | |
: m_func(std::move(other.m_func)) | |
, m_args(std::move(other.m_args)) | |
{ | |
m_packed = pack(m_func); | |
} | |
private: | |
std::function<void(ARGS...)> m_func; | |
std::function<void()> m_packed; | |
std::tuple<std::shared_ptr<OrgT<ARGS>>...> m_args; | |
private: | |
void unpacker(std::function<void(ARGS...)> func, std::shared_ptr<OrgT<ARGS>>... args) | |
{ | |
func(*args...); | |
} | |
template <std::size_t... I> | |
std::function<void()> packImpl(std::function<void(ARGS...)> func, std::index_sequence<I...>) | |
{ | |
return std::bind(&Action::unpacker, this, func, std::get<I>(m_args)...); | |
} | |
std::function<void()> pack(std::function<void(ARGS...)> func) | |
{ | |
return packImpl(func, std::index_sequence_for<ARGS...>{}); | |
} | |
private: | |
template <std::size_t... I> | |
void copyArgumentsImpl(const std::tuple<std::shared_ptr<OrgT<ARGS>>...>& args, std::index_sequence<I...>) | |
{ | |
using ExpandType = int[]; | |
ExpandType{ 0, (*std::get<I>(m_args) = *std::get<I>(args), 0)... }; | |
} | |
void copyArguments(const std::tuple<std::shared_ptr<OrgT<ARGS>>...>& args) | |
{ | |
copyArgumentsImpl(args, std::index_sequence_for<ARGS...>{}); | |
} | |
public: | |
void call() | |
{ | |
m_packed(); | |
} | |
void call(ARGS&&... args) | |
{ | |
m_func(std::forward<ARGS>(args)...); | |
} | |
public: | |
void operator()() | |
{ | |
call(); | |
} | |
void operator()(ARGS&&... args) | |
{ | |
call(std::forward<ARGS>(args)...); | |
} | |
public: | |
Action& operator=(const Action& other) | |
{ | |
if (this == &other) | |
return *this; | |
m_func = other.m_func; | |
copyArguments(other.m_args); | |
m_packed = pack(other.m_func); | |
return *this; | |
} | |
Action& operator=(Action&& other) | |
{ | |
if (this == &other) | |
return *this; | |
m_func = std::move(other.m_func); | |
m_args = std::move(other.m_args); | |
m_packed = pack(m_func); | |
return *this; | |
} | |
}; | |
template <> | |
class Action<> | |
{ | |
public: | |
Action(std::function<void()> func) | |
: m_func(func) | |
{ } | |
Action(const Action&) = default; | |
Action(Action&&) = default; | |
private: | |
std::function<void()> m_func; | |
public: | |
void call() | |
{ | |
m_func(); | |
} | |
public: | |
void operator()() | |
{ | |
call(); | |
} | |
public: | |
Action& operator=(const Action&) = default; | |
Action& operator=(Action&&) = default; | |
}; | |
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 "Action.hpp" | |
using namespace std; | |
int main() | |
{ | |
int foo = 0; | |
Action<int&> f1 = [](auto& data) | |
{ | |
cout << ++data << endl; | |
}; | |
// 포함 변수의 값이 잘 유지되는지 확인. | |
f1(); //> 1 | |
f1(); //> 2 | |
f1(); //> 3 | |
// 직접 인수를 넣을 수 있는지 확인. | |
f1(foo); //> 1 | |
f1(foo); //> 2 | |
cout << "foo : " << foo << endl; | |
// 인수를 직접 넣으면 포함 변수 대신 들어가서 포함 변수에 영향을 안주는 것을 확인. | |
f1(); //> 4 | |
// 복사 생성자 확인. | |
auto f2 = f1; | |
// 포함 변수의 값이 복사 되었는지 확인. | |
f2(); //> 5 | |
f2(); //> 6 | |
f2(); //> 7 | |
// 함수와 포함 변수의 값은 복사되지만 포함 변수 자체는 각각 독립적으로 존재함을 확인. | |
f1(); //> 5 | |
f1(); //> 6 | |
// 대입 연산자 확인. | |
f1 = f2; | |
f1(); //> 8 | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment