C ++模板函数,它采用具有特定返回类型

时间:2016-08-10 22:01:06

标签: c++ templates

我正在用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 ::

等标准实现了列表,向量或映射之类的东西

3 个答案:

答案 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