接受具有特定返回类型的函数类型的c++模板函数
C++ template function that takes a function type with specific return type
我正在用c++的模板做一些魔术,想尝试一下。
在这种情况下,我写了一个朴素的泛型列表实现,List
类型和ListElement
类型包含数据。
现在我已经编写了一个模板化的"for each call"函数,它接受任意类型的成员函数类型,该类型存储在具有任意参数列表的列表中,并使用给定的参数对列表中的每个元素调用该成员函数:
template<typename function, typename ... arguments>
void for_each_call(function call, arguments ... args)
{
for(ListElement * current = this->first; current != nullptr; current = current->next)
{
(current->value->*call)(args ...);
}
}
这样做的问题是,我不能对被调用函数的返回值"反应"。虽然我不想实现.map
功能!
现在我想实现一个"for each call until",它对列表中的值调用函数,直到调用返回"true",然后停止。为此,我需要将作为模板参数插入的函数限制为特定返回布尔值的任何类型的函数。我四处输入,直到编译器停止抱怨,得到这个:
template<bool (*function), typename ... arguments>
void for_each_call_until(arguments ... args)
{
for(ListElement * current = this->first; current != nullptr; current = current->next)
{
if((current->value->*function)(args ...)) break;
}
}
这里发生了什么,这是正确的方法吗?如果不是,什么是正确的方法?
编辑:由于有些人建议使用std::命名空间中的函数:在这些小的培训课程中,我尽量避免使用std::,就好像我想要使用std::一样,我不会自己编写这些像列表、向量或映射这样的小的标准化实现,而是使用std::或boost::首先,这种方法是不必要的限制:
(current->value->*call)(args ...);
如果要求成员函数,则实际上只能执行少量操作。如果打电话的人想做更多,他们就完蛋了。相反,泛化并传递current->value
作为第一个参数:
template<typename function, typename ... arguments>
void for_each_call(function call, arguments ... args)
{
for(ListElement * current = this->first; current != nullptr; current = current->next)
{
call(current->value, args...);
}
}
这适用于所有的情况,就像以前一样-以前你会传递&Class::mem
,而不是传递std::mem_fn(&Class::mem)
-但现在你可以传递任何类型的可调用对象。
现在进入你的主要问题。你不需要做任何不同的事情。只使用
call()
:
的结果template<typename function, typename ... arguments>
void for_each_call(function call, arguments ... args)
{
for(ListElement* current = this->first; current != nullptr; current = current->next)
{
if (call(current->value, args...)) {
break;
}
}
}
就是这样。如果用户提供的可调用对象没有返回上下文可转换为bool
的内容,则会得到编译错误。为什么限制只返回bool
?
如果你真的只需要bool
,抛出一个静态断言:
template<typename function, typename ... arguments>
void for_each_call(function call, arguments ... args)
{
static_assert(std::is_same<decltype(call(this->first->value, args...)), bool>::value, "Must be bool!");
// rest...
}
注意:您可能希望通过引用const
来获取arguments...
,以避免大量复制。
从这里开始,向您展示成员函数指针是如何工作的:
class Foo {
public:
bool test() { return true; }
};
/// The function takes a member function of a class T and its arguments.
template<typename T, typename... Args>
void for_each_call_until(bool (T::*member_function)(Args...),
Args&& ... args) {
T obj; // Instantiate an example object.
bool rts = (obj.*member_function)(std::forward<Args>(args)...);
if (rts == false) { // Check for the result of the member function
// close
}
// ...
}
你的函数可以像这样:
template<typename... Args>
void for_each_call_until(bool (ListElement::*member_function)(Args...),
Args&& ... args) {
for ( /* iteration over pointers */ ) {
bool rts = (current->*member_function)(std::forward<Args>(args)...);
if (rts == false) {
// break
}
// ...
}
}
一个简单的解决方案是使用部分专门化来强制编译错误:
#include <type_traits>
#include <utility>
template<typename T> struct is_bool;
template<> struct is_bool<bool> { typedef int value; };
template<typename function, typename ... arguments>
void for_each_call(function call, arguments && ... args)
{
typedef decltype(call(std::forward<arguments>(args)...)) ret_type;
typedef typename is_bool<ret_type>::value x;
call(std::forward<arguments>(args)...);
}
bool foo(int, int) {} // Compiles
// int foo(int, int) {} // Does not compile
int main()
{
for_each_call(foo, 4, 2);
return 0;
}
- 为什么在我的函数类型后使用引用运算符 (&) 允许我修改它返回的值?
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- 是否有任何建议来统一函数类型限定符并简化可恶的函数类型?
- 关于 C++ 中的函数类型定义
- 用于检测函数类型是否为否的特征
- 函数类型参数的模板参数推导
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- C++无效的函数类型转换
- STL 函数和函数类型与函数指针类型
- 如何将result_of与函数类型定义一起使用
- 将模板(没有规范)传递给 std::thread() 会出现错误:<未解析的重载函数类型>匹配错误
- C++ 编译错误:gnu_printf是无法识别的格式函数类型
- 专门用于"direct"函数类型(与函数指针类型相对)
- 将函数类型作为模板参数传递不会编译
- 通过参数传递 lambda(无函数类型模板)
- 如何在模板参数中分离函数类型返回类型和参数
- 为什么比较函数类型需要指定为模板参数?
- 带有限定符的函数类型定义用例
- 如何声明对函数类型的常量引用
- 非类型模板参数允许各种函数类型?