e.s*_*hen 17 c++ function-pointers callback c++11 std-function
如果你有一个模板化的类或模板化的函数(或两者的组合),你如何绑定该函数,(保留模板类型参数)?
我在下面的帖子中给出了一些关于基本语法的帮助,用显式模板类型参数绑定到函数,但是在这个过程中失去了提供模板类型参数的能力.
是否有可能使其工作,以便仍然可以提供未来调用的模板类型参数?
清理过这段代码很多,但显然无法编译,因为我找不到正确的语法,(有没有办法做到这一点)?
删除了"向量"要求以简化此操作:
谢谢您的帮助!
#include <functional>
#include <vector>
#include <string>
/***************************************/
template <typename CommandTemplateType>
class Storage
{
public:
// No idea how to define this vector to allow Template Parameters
// static std::vector<std::function<void<ParameterTemplateType>
// (std::shared_ptr<ParameterTemplateType>)>> Functions;
// I really don't need the collection, a single member would kick start my research:
static std::function<void<ParameterTemplateType>(std::shared_ptr<ParameterTemplateType>)> Function;
template <typename ParameterTemplateType>
static void Execute(ParameterTemplateType parameter)
{
// Look up index, or loop through all..
// I am trying to invoke the bound function with a template param:
// Functions[index]<ParameterTemplateType>(parameter);
// preferably, just:
Function<ParameterTempalteType>(parameter);
}
};
/***************************************/
template <typename TemplateType>
class MyClass
{
template <typename ParameterTemplateType>
void MyFunction(ParameterTemplateType myParameter)
{
// Do something;
}
MyClass()
{
std::string parameter = L"Test String";
// Do not know how to include the
// template<typename ParameterTemplateType> definition to bind call.
// Storage::Functions.push_back(
// std::bind(&MyClass::MyFunction<ParameterTemplateType>,
// this, std::placeholders::_1));
// Or just something like:
Storage::Function = std::bind(&MyClass::MyFunction<ParameterTemplateType>,
this, std::placeholders::_1));
/***************************************/
// Call the bound function with an explicit parameter somehow:
std::string parameter = L"Test String";
Storage::Execute<std::string>(parameter);
}
};
Run Code Online (Sandbox Code Playgroud)
e.s*_*hen 12
关键问题是在C++ 11中你不能做类似的事情:
// Doesn't compile
template <typename TemplateType>
static std::function<void(std::shared_ptr<TemplateType>)> Function;
Run Code Online (Sandbox Code Playgroud)
类和函数可以是模板化的,但不是成员属性.
"魔术"是:
/*******************************************************************/
// Define a Function Pointer in a Container
class Storage
{
template <typename TemplateType>
struct FunctionContainer {
static std::function<void(std::shared_ptr<TemplateType>)> Function;
};
};
/*******************************************************************/
// Initialize FunctionContainer's Static Function Pointer if using static pointer.
template <typename TemplateType>
std::function<void(std::shared_ptr<TemplateType>)> Storage
::FunctionContainer<TemplateType>::Function;
Run Code Online (Sandbox Code Playgroud)
然后,您可以将模板化函数绑定到此函数,如:
// Bind Function Pointer in Container to a Local Function
class MyClass
{
template <typename TemplateType>
void MyFunction(std::shared_ptr<TemplateType> parameter)
{
// Do something.
// You can make this templated or non-templated.
}
MyClass()
{
// If you really want, you can templatize std::string in the following:
Storage::FunctionContainer<std::string>::Function
= std::bind(&MyFunction<std::string>, this, std::placeholders::_1);
}
}
Run Code Online (Sandbox Code Playgroud)
您可以调用所有这些并提供模板化类型参数,如下所示:
//Invocation
std::shared_ptr<std::string> parameter;
parameter->get() = "Hello World".
Storage::FunctionContainer<std::string>::Function(parameter);
Run Code Online (Sandbox Code Playgroud)
Jos*_*eld 10
模板参数std::function应该是模板类型替换完成后函数的签名.在你的情况,既不TemplateType也不FunctionTemplateType对成员函数的签名效果MyFunction-它总是返回std::string,并采取单一的std::string参数.因此,std::function你要存放在你的std::vector应该是:
static std::vector<std::function<std::string(std::string)>> Functions;
Run Code Online (Sandbox Code Playgroud)
回想一下,成员函数有一个隐含的第一个参数this.您需要将第一个参数绑定MyClass<...>::MyFunc<...>到要调用它的对象.据推测,既然您在MyClass构造函数中绑定了函数,那么您希望该对象成为该MyClass实例.这意味着你push_back应该看起来像这样:
Storage::Functions.push_back(
std::bind(&MyClass<TemplateType>::MyFunction<int>, this,
std::placeholders::_1)
);
Run Code Online (Sandbox Code Playgroud)
现在,推入的函数Functions绑定到您的MyClass对象并采用单个参数类型std::string.您可以像这样调用以下函数之一:
Storage::Functions[0]("something");
Run Code Online (Sandbox Code Playgroud)
小智 5
如果我理解你的话...... :)
您想要做的是不可能的,因为对于模板<class T> void foo(T)函数foo <int>()和foo <double>属于不同的类型,并且您无法创建向量保持指向这两个函数的向量,因为矢量是同质的容器.
为了克服这个问题,我们可以使用boost :: variant <>来存储指向不同类型函数的指针或存储函数的参数.
template<class T> void foo(T);
typedef boost::variant<void (*)(int), void (*)(double)> func_ptr_variant;
std::vector<func_ptr_variant> v;
v.push_back(foo<int>);
v.push_back(foo<double>);
typedef boost::variant<int, double> argument;
std::vector<void (*)(argument)) v;
v.push_back(foo);
v.push_back(bar);
// foo and bar are defined as void foo(argument a) and void bar(argument a)
Run Code Online (Sandbox Code Playgroud)
不幸的是,在任何情况下,您都需要在将函数模板插入容器之前对其进行实例化,因为C++无法动态执行代码生成.我认为您可能知道函数可能使用的所有可能类型的参数,因此可能不是问题.