가변 템플릿 인수를 저장하는 방법은 무엇입니까?
나중에 사용하기 위해 어떻게 든 매개 변수 팩을 저장할 수 있습니까?
template <typename... T>
class Action {
private:
std::function<void(T...)> f;
T... args; // <--- something like this
public:
Action(std::function<void(T...)> f, T... args) : f(f), args(args) {}
void act(){
f(args); // <--- such that this will be possible
}
}
그런 다음 나중에 :
void main(){
Action<int,int> add([](int x, int y){std::cout << (x+y);}, 3, 4);
//...
add.act();
}
여기서 원하는 작업을 수행하려면 템플릿 인수를 튜플에 저장해야합니다.
std::tuple<Ts...> args;
또한 생성자를 약간 변경해야합니다. 특히로 초기화 args
하고 std::make_tuple
매개 변수 목록에서 범용 참조를 허용합니다.
template <typename F, typename... Args>
Action(F&& func, Args&&... args)
: f(std::forward<F>(func)),
args(std::forward<Args>(args)...)
{}
또한 다음과 같이 시퀀스 생성기를 설정해야합니다.
namespace helper
{
template <int... Is>
struct index {};
template <int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> {};
template <int... Is>
struct gen_seq<0, Is...> : index<Is...> {};
}
그리고 이러한 생성기를 사용하는 방식으로 메서드를 구현할 수 있습니다.
template <typename... Args, int... Is>
void func(std::tuple<Args...>& tup, helper::index<Is...>)
{
f(std::get<Is>(tup)...);
}
template <typename... Args>
void func(std::tuple<Args...>& tup)
{
func(tup, helper::gen_seq<sizeof...(Args)>{});
}
void act()
{
func(args);
}
그리고 그것! 이제 수업은 다음과 같이 보일 것입니다.
template <typename... Ts>
class Action
{
private:
std::function<void (Ts...)> f;
std::tuple<Ts...> args;
public:
template <typename F, typename... Args>
Action(F&& func, Args&&... args)
: f(std::forward<F>(func)),
args(std::forward<Args>(args)...)
{}
template <typename... Args, int... Is>
void func(std::tuple<Args...>& tup, helper::index<Is...>)
{
f(std::get<Is>(tup)...);
}
template <typename... Args>
void func(std::tuple<Args...>& tup)
{
func(tup, helper::gen_seq<sizeof...(Args)>{});
}
void act()
{
func(args);
}
};
업데이트 : 다음은 템플릿 인수를 지정할 필요가없는 도우미 메서드입니다.
template <typename F, typename... Args>
Action<Args...> make_action(F&& f, Args&&... args)
{
return Action<Args...>(std::forward<F>(f), std::forward<Args>(args)...);
}
int main()
{
auto add = make_action([] (int a, int b) { std::cout << a + b; }, 2, 3);
add.act();
}
You can use std::bind(f,args...)
for this. It will generate a movable and possibly copyable object that stores a copy of the function object and of each of the arguments for later use:
#include <iostream>
#include <utility>
#include <functional>
template <typename... T>
class Action {
public:
using bind_type = decltype(std::bind(std::declval<std::function<void(T...)>>(),std::declval<T>()...));
template <typename... ConstrT>
Action(std::function<void(T...)> f, ConstrT&&... args)
: bind_(f,std::forward<ConstrT>(args)...)
{ }
void act()
{ bind_(); }
private:
bind_type bind_;
};
int main()
{
Action<int,int> add([](int x, int y)
{ std::cout << (x+y) << std::endl; },
3, 4);
add.act();
return 0;
}
Notice that std::bind
is a function and you need to store, as data member, the result of calling it. The data type of that result is not easy to predict (the Standard does not even specify it precisely), so I use a combination of decltype
and std::declval
to compute that data type at compile time. See the definition of Action::bind_type
above.
Also notice how I used universal references in the templated constructor. This ensures that you can pass arguments that do not match the class template parameters T...
exactly (e.g. you can use rvalue references to some of the T
and you will get them forwarded as-is to the bind
call.)
Final note: If you want to store arguments as references (so that the function you pass can modify, rather than merely use, them), you need to use std::ref
to wrap them in reference objects. Merely passing a T &
will create a copy of the value, not a reference.
I think you have an XY problem. Why go to all the trouble to store the parameter pack when you could just use a lambda at the callsite? i.e.,
#include <functional>
#include <iostream>
typedef std::function<void()> Action;
void callback(int n, const char* s) {
std::cout << s << ": " << n << '\n';
}
int main() {
Action a{[]{callback(13, "foo");}};
a();
}
참고URL : https://stackoverflow.com/questions/16868129/how-to-store-variadic-template-arguments
'program tip' 카테고리의 다른 글
이 모든 * .FileListAbsolute.txt 파일은 무엇입니까? (0) | 2020.10.15 |
---|---|
라즈베리 파이의 모노 (0) | 2020.10.15 |
메타 이름과 메타 속성의 차이점은 무엇입니까? (0) | 2020.10.15 |
Linux 동적 링커에서 "사용 가능한 버전 정보 없음"오류는 무엇을 의미합니까? (0) | 2020.10.15 |
Eclipse 플러그인 대 기능 대 드롭 인 (0) | 2020.10.15 |