0

我的课程N采用一种类型T和不同数量的类型F...

真正发生的是我正在重载operator()以获取函数引用以及该函数将提供的参数。这就像一个绑定函数。但是当函数引用返回时void,我不希望能够std::cout从该函数调用的值operator()。因此,当函数引用的返回类型为时,我添加了operator<<for的重载以不做任何事情,但我想我没有正确写出函数签名,因为我得到了错误。std::coutvoid

#include <iostream>
#include <utility>

template <typename T>
struct N;

template <typename T, typename ... F>
struct N<T(F...)> {
    T operator()(T (&t)(F...), F &&... f) {
        return t(std::forward<F>(f)...);
    }
};

template <typename ... T>
void operator<< (std::ostream &, const N<void(T...)> &) {}
                                 // don't do anything when void

void f(int, int) {}

int main() {

    N<void(int, int)> bind;

    std::cout << bind(f, 5, 4); // errors

}

我得到的错误很长,所以我不会发布它们;它们是在返回的函数上打印的典型错误消息void

上面的代码失败了,因为我正在打印一个返回的函数void;这就是功能f。我的过载operator<<似乎没有影响任何事情。我在这里做错了什么?如果您需要更多详细信息,请直说。谢谢。

4

1 回答 1

3

在您的代码中,您明确调用operator()object bind。(顺便说一句,不要使用该bind对象的名称,std::bind太有名了,它会混淆人们)

该代码执行您要求它执行的操作。它称为函子。哪个返回void

重载中的任何operator<<内容都不会对被调用的函子产生任何影响。

现在它被调用了,我们看到我们有一个std::cout << void-- 它也与你的operator<<.

替换std::cout << bind(f, 5, 4); // errorsstd::cout << bind;并且您的重载operator<<将被调用。

C++ 中的操作顺序不是从左到右的。 a << b(c)先评估tmp=b(c),再评估a << tmp

现在,如何处理此问题的一个示例是将您的N类型专门化为,当它返回 a 时void,改为返回 a pseudo_voidpseudo_void阻止所有使用,除非您有一个<<仅包含return os; (哦,并且operator<<( ostream& os, blah )应该始终返回os)的重载。

这可能会导致其他问题。例如,您需要一个“摆脱伪空”特征类等。但它为您提供了您想要的语法。

于 2012-12-22T03:55:57.593 回答