流操纵器的免费函数与直接重载运算符<<

问题描述

我正在研究自定义流类的可能设计。在现场和场外搜索了半个小时都没有找到我的问题的答案,所以我提出了一个新问题。

std::endl为例。如果我没有记错的话,它被指定为大致像这样工作(认为这是“幻灯片代码”):

struct ostream
{
    using FManip = ostream& (*)(ostream&);
    ostream& operator<<(FManip f)
    {
        return f(*this);
    }
};

ostream& endl(ostream& s)
{
    /* ...do whatever... */
    return s;
}

https://godbolt.org/z/6MP5cseas

但是,我不清楚这样做的好处是什么,而不是拥有标记对象并直接为它们实现 operator<<

struct ostream
{
};

// (reserved name - use whatever convention fits when writing library code)
struct _EndlManipTag {};
static constexpr _EndlManipTag endl;

ostream& operator<<(ostream& s,_EndlManipTag tag)
{
    /* ...do whatever... */
    return s;
}

int main()
{
  ostream os;
  os << endl;
}

https://godbolt.org/z/dzj7v8fse

我知道第一个版本为额外的操纵器编写的代码略少。这不是最糟糕的原因,但它似乎更令人费解(有多少人知道 std::endl 实际上是一个函数),并且偏离了具有参数的操纵器的实现(例如 std::setw(n) 返回一个存储 n 并且存在适当的 operator<< 重载的对象 - 非常接近第二个片段)。

我想知道这里是否还有其他考虑因素(在标准化时或在查看当前 C++ 版本时)。也许重载决议的微妙之处?编译速度?易于优化?模板友好?错误信息?或者我在新代码中选择哪种方法根本无关紧要?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)