【发布时间】:2016-08-10 22:01:05
【问题描述】:
我正在用 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) 的返回值分配给一个布尔局部变量。除非函数实际返回布尔值,否则此分配将无法编译,因此实际上您将函数限制为仅接受返回布尔值的函数。如果我没记错的话,产生的编译错误实际上是非常有用的,例如“无法将
转换为布尔值。” -
如果函数返回一个int,这种方法也可以,这是错误的。
-
好吧,我们谈论的是 c++,作为返回类型的 bool 和 int 背后的语义以我们都不喜欢思考的方式交织在一起。
-
@SamVarshavchik bool 实际上在我认为的某些标准版本中类型定义为 int 。如果您真的需要这种安全性,那么定义您自己的类型安全 bool 枚举然后只接受输出该枚举成员的函数怎么样。
-
我不需要那种安全性,这真的只是我想到的将某些东西传递给“如果”的最好方法,不需要考虑太多