【问题标题】:Why a function pointer is not captured by universal reference?为什么通用引用不捕获函数指针?
【发布时间】:2013-10-03 12:54:43
【问题描述】:

在实现一个简单的记录器时

struct DebugOutput {
    DebugOutput(std::ostream& out = std::cerr) : m_Out(out) {}

    template<typename T>
    inline DebugOutput& operator <<(T&& value) {
        m_Out << value;
        return *this;
    }
private:
    std::ostream& m_Out;
};

我发现std::endl 不会被universal reference 捕获。

DebugOutput dbg;
dgb << std::endl;

我发现了这个this post,它解释了您需要在结构中添加一个重载函数,该函数专门采用函数指针签名,即:

typedef std::ostream& (*StandardEndLine)(std::ostream&);
inline DebugOutput& operator<<(StandardEndLine manip) {
    return *this;
}

为什么函数指针没有被通用引用捕获?不是int 或void* 的类型吗?

【问题讨论】:

标签: c++ c++11


【解决方案1】:

函数(指针)可以绑定到通用引用。示例:

void f(int) {}

template <typename T>
void foo(T&&) {}

foo(f); // OK

但是,重载的函数不能。也就是说,如果您添加第二个重载 f,比如说,

void f(double) {}

调用foo(f) 将失败。

把自己放在编译器的鞋子上。需要将f 传递给foo,并且有两个名为f 的函数,每个函数都有不同的类型。如果我们告知类型,那么编译器可以明确地选择正确的f。例如,

foo(static_cast<void (*)(int)>(f));

编译良好,并将void f(int)(在函数到指针转换后)传递给foo。

但是,我们不会通知类型。我们宁愿让编译器推导出它。

与f 类似,相同的参数也适用于std::endl,因为这是一个函数模板,因此名称std::endl 代表一组函数,它们都具有相同的名称但类型不同。

现在,您可以看到错误的原因是我们提供了一个重载集并要求进行类型推导。因此,这并不是通用引用所特有的。

std::cout &lt;&lt; std::endl 有效,因为basic_ostream::operator &lt;&lt; 不是模板并且不会尝试推断传递参数的类型。这是一个接受一种特定类型的std::endl 的函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-10
    • 2013-02-09
    • 1970-01-01
    相关资源
    最近更新 更多