std::function 到可变成员函数,然后绑定可变模板参数
std::function to variadic member function and then bind variadic template arguments
我有两个可变 class 成员函数。
当调用第一个 Init(...)
时,我想为第二个 class 成员函数创建一个 std::function,然后将 Init(...)
的参数绑定到函数指针。
所以稍后我可以调用 mf_()
而不必再次将所有参数传递给 Reset(...)
我想避免将其设为模板 class 并将参数存储在元组中。
我正在努力使下面的示例起作用:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
class Foo
{
public:
template<typename... T>
void Init(T&... args)
{
cout << __func__ << endl;
Print(args...);
// bind args.. to Reset ..
mf_ = std::bind(&Reset, args...);
// mf_ = std::bind(&Foo::Reset, this, args...); ???
}
template<typename... T>
void Reset(T&... args)
{
cout << __func__ << endl;
}
// std::function to Reset(...)
std::function<void()> mf_;
private:
template<typename First>
void Print(First& arg)
{
cout << arg << endl;
}
template<typename First, typename... Rest>
void Print(First& arg, Rest&... args)
{
cout << arg << " ";
Print(args...);
}
};
int main()
{
int arg1 = 1;
int arg2 = 2;
string arg3 { "test" };
double arg4 = 1.10;
Foo foo;
foo.Init(arg1, arg2, arg3, arg4);
//foo.mf_();
return 0;
}
Link 举个例子:http://cpp.sh/4ylm
当我编译时,我得到一个错误
template argument deduction/substitution failed: 17:37:
note: couldn't deduce template parameter '_Result'
问题是 &Reset
不是有效的成员指针表达式。
你需要说 &Foo::Reset
来形成一个指向成员函数的指针,你还需要提供 this
指针,所以你几乎是正确的:
// mf_ = std::bind(&Foo::Reset, this, args...); ???
但它仍然无效,因为 Reset
是一个函数模板,因此您需要说明您指的是哪个模板特化。
您可以通过提供显式模板参数列表来告诉编译器您想要哪种特化:
mf_ = std::bind(&Foo::Reset<T&...>, this, args...);
或者通过创建一个正确类型的变量,从 &Foo::Reset
初始化,这允许编译器推断出您指的是哪个特化:
void (Foo::*f)(T&...) = &Foo::Reset;
mf_ = std::bind(f, this, args...);
或者通过为正确的类型创建一个 typedef,并将 &Foo::Reset
转换为该类型:
using pmf_type = void (Foo::*)(T&...);
mf_ = std::bind((pmf_type)&Foo::Reset, this, args...);
我有两个可变 class 成员函数。
当调用第一个 Init(...)
时,我想为第二个 class 成员函数创建一个 std::function,然后将 Init(...)
的参数绑定到函数指针。
所以稍后我可以调用 mf_()
而不必再次将所有参数传递给 Reset(...)
我想避免将其设为模板 class 并将参数存储在元组中。
我正在努力使下面的示例起作用:
#include <iostream>
#include <string>
#include <functional>
using namespace std;
class Foo
{
public:
template<typename... T>
void Init(T&... args)
{
cout << __func__ << endl;
Print(args...);
// bind args.. to Reset ..
mf_ = std::bind(&Reset, args...);
// mf_ = std::bind(&Foo::Reset, this, args...); ???
}
template<typename... T>
void Reset(T&... args)
{
cout << __func__ << endl;
}
// std::function to Reset(...)
std::function<void()> mf_;
private:
template<typename First>
void Print(First& arg)
{
cout << arg << endl;
}
template<typename First, typename... Rest>
void Print(First& arg, Rest&... args)
{
cout << arg << " ";
Print(args...);
}
};
int main()
{
int arg1 = 1;
int arg2 = 2;
string arg3 { "test" };
double arg4 = 1.10;
Foo foo;
foo.Init(arg1, arg2, arg3, arg4);
//foo.mf_();
return 0;
}
Link 举个例子:http://cpp.sh/4ylm
当我编译时,我得到一个错误
template argument deduction/substitution failed: 17:37:
note: couldn't deduce template parameter '_Result'
问题是 &Reset
不是有效的成员指针表达式。
你需要说 &Foo::Reset
来形成一个指向成员函数的指针,你还需要提供 this
指针,所以你几乎是正确的:
// mf_ = std::bind(&Foo::Reset, this, args...); ???
但它仍然无效,因为 Reset
是一个函数模板,因此您需要说明您指的是哪个模板特化。
您可以通过提供显式模板参数列表来告诉编译器您想要哪种特化:
mf_ = std::bind(&Foo::Reset<T&...>, this, args...);
或者通过创建一个正确类型的变量,从 &Foo::Reset
初始化,这允许编译器推断出您指的是哪个特化:
void (Foo::*f)(T&...) = &Foo::Reset;
mf_ = std::bind(f, this, args...);
或者通过为正确的类型创建一个 typedef,并将 &Foo::Reset
转换为该类型:
using pmf_type = void (Foo::*)(T&...);
mf_ = std::bind((pmf_type)&Foo::Reset, this, args...);