在哪里为tr1 :: array添加重载运算符?

时间:2010-05-10 07:50:33

标签: c++ namespaces operator-overloading

由于我需要为operator&添加std::tr1::array<bool, N>,我写了以下几行

template<std::size_t N>
std::tr1::array<bool, N>
operator& (const std::tr1::array<bool, N>& a,
           const std::tr1::array<bool, N>& b)
{
  std::tr1::array<bool, N> result;
  std::transform(a.begin(), a.end(), b.begin(), result.begin(),
                 std::logical_and<bool>());
  return result;
}

现在我不知道我要把这个函数放在哪个命名空间中。我将std命名空间视为限制区域。用户只允许添加完全特化和重载的功能模板。将它放入全局命名空间不是“允许”,以防止污染全局命名空间和与其他声明冲突。最后将此函数放入项目的命名空间不起作用,因为编译器不会在那里找到它。

我最擅长的是什么?我不想写一个新的数组类放入项目命名空间。因为在这种情况下,编译器将通过参数依赖名称查找找到正确的命名空间。或者这是唯一可能的方法,因为为现有类编写一个新的运算符意味着扩展它们的接口,这对于标准类也是不允许的?

2 个答案:

答案 0 :(得分:7)

我完全支持GMan和sbk,他们告诉你使用命名函数而不是运算符。 与流行的观点相反,重载运算符总是差错,因为它几乎从不会增加代码的清晰度。 令人惊讶的是,很少有例外。其中包括流输入和输出运算符以及算术运算符,如果您实现类似数字的类型。 (而且在一本书中教你操作员超载的可能性有多大?)请注意,有些人对+的{​​{1}}(以及+=的std lib过载感到不满同样的原因(和其他人一样,std::string代表数字,但不适用于字符串) - 而IMO他们确实有一个观点。

无论如何,如果有人想要这样做,尽管有各种建议: 当您尝试调用运算符时,编译器会尝试在中调用它的名称空间,所有封闭的名称空间以及所有参数的名称空间中找到它。 (后者称为参数依赖查找或Koenig查找。)参数的名称空间为a+b==b+a,您不能添加重载。离开名称空间后,在中调用运算符及其封闭名称空间 - 包括全局名称空间,其中包含所有其他名称空间< - 以放置运算符in。

因此,如果您想要在所有警告的情况下实现它,请将其放在使用它的命名空间中。如果在多个命名空间中使用它,请将其放入包含所有这些命名空间的命名空间中。如果这是全局命名空间,那就这样吧。

哦,我是否提到过将其作为重载运算符实现?

答案 1 :(得分:1)

AFAIK,您可以将重载添加到任何命名空间(除了std,因为您不允许向其添加新函数),并且您可以使用using声明使其可见。例如,这就是boost's assign library的工作原理(注意介绍性片段;对于标准库中的先例,请查看rel_ops)。另请注意,您可以限制使用声明的范围,以避免全局污染。

示例,由于旧编译器使用boost::array

#include <boost/array.hpp>
#include <functional>
#include <algorithm>
using boost::array;

namespace bitarray_operators
{
    template <size_t N>
    array<bool, N> operator& (const array<bool, N>& a, const array<bool, N>& b)
    {
        array<bool, N> result;
        std::transform(a.begin(), a.end(), b.begin(), result.begin(), std::logical_and<bool>());
        return result;
    }
}

int main()
{
    using namespace bitarray_operators;      //<-- this makes it possible to find the & operator
    array<bool, 100> a, b, c;
    c = a & b;
}

我同意重载此运算符可能有些疑问。我也不清楚为什么你不使用std::bitset重载这个运算符可能会有更好的性能,因为内部表示更紧凑(每个bool占一位,而不是至少是char的大小)。