隐藏其他运营商一段时间

时间:2015-12-24 10:42:59

标签: c++

在阅读了名称查找规则,重载决议数十次后,我仍感到困惑。

我不确定我问的是我应该问的是什么,但无论如何。 想象一下,我有一些像第三方提供的功能:

namespace some_space {
template<typename Container>
void do_fancy_output(std::ostream& out, const Container& c) {
    for (auto& el : c) { out << el; }
}
} // namespace

并且假设此函数附带了一组准备好的运算符<<重载(为清楚起见,请在some_space命名空间中定义它们)。除此之外,我有自己的一组重载。

问题是:有没有办法打开和关闭特定do_fancy_output()来电的具体操作员重载?实现这一目标的一般架构指南是什么?

2 个答案:

答案 0 :(得分:1)

operator <<是一个像任何其他函数一样的函数。您无法在运行时动态更改函数实现。

你可以做的是:

使用不同的功能

// instead of:
out << el;

// do:
my_left_shift_operation_implementation(out, el);

,或者

制作包装

如果真的喜欢使用<<语法,请创建自己的class MyElement,用于包装MyElement(el),然后在该类型上定义运算符。然后你会有:

out << my_el;
顺便说一句,如果重写操作员是你唯一能做的事情,我肯定会选择第一个解决方案。

根据某些外部因素选择实施

如果您想在一种行为与另一种行为之间切换,请在my_left_shift_operation_implementation

中执行此操作

你甚至可以制作一个Formatter类,可以重写以提供不同的格式化实现。那你就做了:

out << my_formatter.format(el);

答案 1 :(得分:0)

您可以使用hack来覆盖函数中调用的运算符:

  • 首先,您创建自己的命名空间。如果从此命名空间编写对象,则首先在该对象的命名空间中搜索相应的运算符。
  • 其次,您可以在该命名空间中创建函数/运算符,以便根据需要输出对象。
  • 第三,您只需在该命名空间中创建一个引用包装器/代理,这将导致查找首先搜索以前编写的函数。
  • 最后,这有点棘手,你创建了一个序列包装器,它允许像任何容器一样迭代但返回引用包装器而不是实际的对象。

粗略地说,前三个步骤看起来像这样:

namespace special_format
{
    // various functions for writing
    void write(ostream& out, int);
    void write(ostream& out, float);

    // reference wrapper
    template<typename value_type>
    struct ref_wrapper
    {
        value_type const& value;
    };
    // convenience factory function
    template<typename value_type>
    ref_wrapper<value_type>
    ref(value_type const& value)
    {
        ref_wrapper<value_type> r = {value};
        return r;
    }
}

我希望这部分是清楚的。序列包装器的第四部分更具挑战性,因为它包含更多的部分(我太懒了,不想破坏你编写它的全部乐趣)。首先,为了支持基于范围的for循环,您需要提供开始/结束迭代器访问。一种方法是简单地在命名空间中提供普通的begin()end()函数,这些函数将在与该命名空间中的类型一起使用时找到。从那些,你只需返回一个包装容器的迭代器的迭代器。必须将value_type,运算符*和运算符->调整为ref_wrapper类型,以便我们的命名空间内的查找再次启动。