用函数名作为字符串将 std::function 包装在类中
Posted
技术标签:
【中文标题】用函数名作为字符串将 std::function 包装在类中【英文标题】:Wrap std::function in class with function name as string 【发布时间】:2019-07-21 12:10:17 【问题描述】:我正在尝试将std::function
包装在一个类中,并将函数名称的可读string
添加到std::function
。
我确实想出了这个简单的课程 (在 header.hpp 中定义)
template <typename... Args>
class CExtended_Function
public:
explicit CExtended_Function(
const std::function<void(Args...)>& func_type, const std::string& func_name)
: func(func_type)
, function_name(func_name)
/// Function
const std::function<void(Args...)> func;
/// Function Name
const std::string function_name;
;
我自己的 make 函数看起来像这样。想法是将函数名称作为模板参数传递给 make 函数。 make 函数应该创建一个std::function
实例和一个std::string
实例。
(在 header.hpp 中定义)
template <typename Func_T, typename... Args>
CExtended_Function<Args...> Make_Extended_Function()
std::function<void(Args...)> func(Func_T);
std::string func_name(NCommonFunctions::type_name<Func_T>());
CExtended_Function<Args...> res(func, func_name);
return res;
其中type_name<My_Function>()
返回函数的名称为std::string_view
在 header.hpp 中定义
template <class T>
constexpr std::string_view type_name();
但是,当我像这样使用我的 make 函数时
在 source.cpp 中使用
static void Test_Callback();
auto test = Make_Extended_Function<Test_Callback>();
我收到了错误:
符号“Make_Extended_Function”无法解析
你能告诉我为什么会出现这个错误吗?
【问题讨论】:
你是众多尝试implement a template in a .cpp file的人之一吗? 不是所有模板都在头文件中定义和实现。 如果将所有内容放在一个文件中,问题会消失吗? 我写了这个作为答案,但后来我意识到这可能不是问题并删除了它。无论如何,您将函数作为类型参数传递,但它不是类型,请查看 godbolt.org/z/NnESxJ 。这是你想要达到的目标吗?如果你应用我的修复,它会编译吗? @L.F.不,这不是包含问题。 【参考方案1】:您可能需要在代码中更改几件事:
-
Test_Callback 是一个函数,您只能将函数指针作为非类型模板参数传递。 IE。它应该是
auto test = Make_Extended_Function<&Test_Callback>();
;
如果你传递一个函数指针作为模板参数,语法是template<function+pointer_type function pointer>
(类似于模板),所以make_extended_function应该是template <auto Func_T, typename... Args>
CExtended_Function<Args...> Make_Extended_Function()
(我在这里使用“auto”来使事情更容易)。 type_name() 也一样
示例代码:
#include <iostream>
#include <functional>
#include <string_view>
using namespace std;
namespace NCommonFunctions
template <auto T>
std::string type_name() return "a_name";
template <typename... Args>
class CExtended_Function
public:
explicit CExtended_Function(
const std::function<void(Args...)>& func_type, const std::string& func_name)
: func(func_type)
, function_name(func_name)
/// Function
const std::function<void(Args...)> func;
/// Function Name
const std::string function_name;
;
template <auto Func_T, typename... Args>
CExtended_Function<Args...> Make_Extended_Function()
std::function<void(Args...)> func(Func_T);
std::string func_name(NCommonFunctions::type_name<Func_T>());
CExtended_Function<Args...> res(func, func_name);
return res;
void Test_Callback() cout << "test" << endl;
int main ()
auto test = Make_Extended_Function<&Test_Callback>();
test.func();
【讨论】:
【参考方案2】:Make_Extended_Function
需要类型。你提供了函数指针,所以出错了。
更简单的解决方法可能是将Make_Extended_Function
更改为:
template <typename... Args>
CExtended_Function<Args...>
Make_Extended_Function(const std::function<void(Args...)>& f, const std::string& name)
return CExtended_Function<Args...>(f, name);
(但您必须使用std::function
调用它才能允许扣除)。
NCommonFunctions::type_name
似乎与Make_Extended_Function
有相同的问题。
一个可能更好的解决方法是删除 std::function 并直接使用仿函数:
template <typename F>
class CExtended_Function
public:
explicit CExtended_Function(
const F& f, const std::string& name)
: f(f)
, name(name)
F f;
std::string name;
;
【讨论】:
以上是关于用函数名作为字符串将 std::function 包装在类中的主要内容,如果未能解决你的问题,请参考以下文章