我正在用c ++中的模板做一些魔术,想到尝试一些东西。
在这种情况下,我编写了一个天真的通用列表实现,其中包含List
类型和包含数据的ListElement
类型。
现在我已经编写了一个模板化的“每个调用”函数,它使用任意参数列表获取存储在列表中的类型的任意成员函数类型,并使用给定参数调用列表中每个元素上的成员函数:
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 calls”,它调用列表中值的函数,直到调用返回“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 :: namespace中的函数:在这些小训练课程中,我试图避免std ::就像瘟疫一样,好像我想要使用std ::我不会写这些我自己使用std ::或boost :: 等标准实现了列表,向量或映射之类的东西答案 0 :(得分:1)
首先,这种方法有不必要的限制:
(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...
}
注意:您可能希望通过arguments...
引用const
来避免大量复制。
答案 1 :(得分:0)
从此开始,只是为了向您展示成员函数指针是如何工作的:
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
}
// ...
}
}
答案 2 :(得分:-1)
一个简单的解决方案涉及使用部分特化来强制编译错误:
where