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

phl*_*psy 2 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;
}
Run Code Online (Sandbox Code Playgroud)

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

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

sbi*_*sbi 7

我完全支持GMan和sbk,他们告诉你使用命名函数而不是运算符.与普遍认为的相反,重载运算符总是几乎是错误的,因为它几乎从未增加代码的清晰度.令人惊讶的是,很少有例外.其中包括流输入和输出运算符以及算术运算符,如果您实现类似数字的类型.(而且是多么容易的一本书教你操作符重载的那个之外?)请注意,有些人于标准库超载皱眉+(和+=,当然)为std::string出于同样的原因(和其他人一样,a+b==b+a适用于数字,但不对于字符串) - 和IMO他们确实有一点.

无论如何,如果有人想要这样做,尽管有所有建议:
当你尝试调用运算符时,编译器会尝试在调用它的命名空间,所有封闭的命名空间以及所有参数命名空间中找到它.(后者称为参数依赖查找或Koenig查找.)参数的名称空间是std,您不能添加重载.这样就可以调用操作符所在命名空间及其封闭的命名空间 - 包括包含所有其他命名空间全局命名空间 - 以将操作符放入其中.

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

哦,我提到你不应该它作为一个重载运算符实现吗?

  • @peterchen:没有反对重载运算符的论据_in general_,有时重载很好.只是这些场合比大多数初学者想象的要少.如果运算符在应用程序域中的使用是无可争议的,那么一个好的经验法则可能是重载运算符.(如果人们发生争议,尽管你认为他们不应该这样做,但这并不是无可争议的.如果有疑问,请使用函数.) (2认同)