C++如何使用std::bind/std::函数引用模板函数
C++ How to Reference Templated Functions using std::bind / 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);
}
};
关键问题是在C++11中,您不能执行以下操作:
// Doesn't compile
template <typename TemplateType>
static std::function<void(std::shared_ptr<TemplateType>)> Function;
类和函数可以是模板化的,但不能是成员属性。
"魔术"是:
/*******************************************************************/
// 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;
然后,您可以将模板化的函数绑定到此函数,如:
// 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);
}
}
您可以调用所有这些,并提供一个模板化的类型参数,如下所示:
//Invocation
std::shared_ptr<std::string> parameter;
parameter->get() = "Hello World".
Storage::FunctionContainer<std::string>::Function(parameter);
std::function
的模板参数应该是完成模板类型替换后函数的签名。在您的情况下,TemplateType
和FunctionTemplateType
都不会对成员函数MyFunction
的签名产生影响——它将始终返回一个std::string
并接受一个单独的std::string
参数。因此,要存储在std::vector
中的std::function
应该是:
static std::vector<std::function<std::string(std::string)>> Functions;
回想一下,成员函数有一个隐含的第一个参数this
。您需要将MyClass<...>::MyFunc<...>
的第一个参数绑定到您希望对其进行调用的对象。很可能,由于您在MyClass
的构造函数中绑定函数,所以您希望该对象是MyClass
实例。这意味着你的push_back
应该是这样的:
Storage::Functions.push_back(
std::bind(&MyClass<TemplateType>::MyFunction<int>, this,
std::placeholders::_1)
);
现在,推送到Functions
中的函数绑定到MyClass
对象,并接受类型为std::string
的单个参数。你可以这样调用其中一个函数:
Storage::Functions[0]("something");
如果我理解得对…:)
您想要做的是不可能的,因为对于template<类T>void foo(T)函数foo<int>()和foo<双>是不同类型的,并且不能直接创建指向这两个函数的向量持有指针,因为向量是同构容器。
为了克服这一点,我们可以使用boost::variation<>存储指向不同类型函数的指针或存储函数的自变量。
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)
不幸的是,在任何情况下,您都需要在将函数模板插入容器之前实例化它们,因为C++不能动态生成代码。我认为,你可能知道函数可能使用的所有可能类型的参数,所以这可能不是问题。
MyClass的c-tor对FunctionTemplateType
一无所知,这就是为什么它只能像这个一样推送回显式专用(对不起,这是我的术语…我不知道正确的术语)
#include <functional>
#include <vector>
#include <string>
struct Storage
{
// Have no idea what this signature should really be:
static std::vector<std::function<void ()>> Functions;
};
std::vector<std::function<void ()>> Storage::Functions;
template <typename TemplateType>
class MyClass
{
template <typename FunctionTemplateType>
std::string MyFunction(std::string myParameter)
{
return "Hellö: " + myParameter;
}
public:
MyClass()
{
Storage::Functions.push_back(
std::bind( & MyClass<TemplateType>::MyFunction<std::string>, this, "borisbn" )
// ^^^^^^^^^^^
);
}
};
int main() {
MyClass<int> obj;
}
liveworkspacelink
- 无法引用该函数" std:: variant <_Types...> operator =",因为此函数已被删除
- 错误:使用已删除的函数"std::unique_ptr<...>
- 我有模板功能.通过使用函数std::for_each,用这个容器中的最大数字替换每个正数
- 如何使用函数std::min()来计算最小值
- 删除了 g++ 在 linux 中basic_stringstream函数 std
- 如何在 c++ 中使用返回类型导出函数 std::map
- 错误:使用已删除的函数"std::atomic<_Tp>::atomic() [_Tp = node]"
- 使用 SFINAE 检查函数 std::to_string 是否存在类型
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误
- 为什么函数 std::basic_streambuf::setg() 需要非常量 agruments
- C++将已删除的函数 std::unique_ptr 与基类一起使用
- 奇怪的错误:当没有真正创建指针时,使用已删除的函数'std::unique_ptr<_Tp,_Dp>::unique_ptr
- 通过模板构造函数(std ::功能和迷你案例)将构造函数触发
- 错误:使用已删除的函数"std::atomic<_Tp>::atomic()
- 错误:使用已删除的函数std::basic_ofstream(OpenCV和C++11)
- 类成员容器迭代器在成员函数std::find中不兼容,但为什么不兼容呢
- 没有构造函数 std::istream_iterator 的实例
- 错误:没有与参数列表匹配的重载函数"std::make_shared"实例
- 错误:使用已删除的函数"std::thread::thread(const std::thread&)"
- 不能在没有对象的情况下调用成员函数 std::string class::function()