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

发布于 2024-08-31 18:05:46 字数 761 浏览 3 评论 0原文

由于我需要为 std::tr1::array 添加一个 operator& 我写了以下几行

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 命名空间视为禁区。仅允许用户添加完全专业化和重载的功能模板。为了防止全局命名空间的污染以及与其他声明的冲突,也不允许将其放入全局命名空间中。最后,将此函数放入项目的命名空间中不起作用,因为编译器在那里找不到它。

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

Since I need to add an operator& for the std::tr1::array<bool, N> I wrote the following lines

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;
}

Now I don't know in which namespace I've to put this function. I considered the std namespace as a restricted area. Only total specialization and overloaded function templates are allowed to be added by the user. Putting it into the global namespace isn't "allowed" either in order to prevent pollution of the global namespace and clashes with other declarations. And finally putting this function into the namespace of the project doesn't work since the compiler won't find it there.

What had I best do? I don't want to write a new array class putted into the project namespace. Because in this case the compiler would find the right namespace via argument dependent name lookup. Or is this the only possible way because writing a new operator for existing classes means extending their interfaces and this isn't allowed either for standard classes?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

月朦胧 2024-09-07 18:05:46

我完全支持 GMan 和 sbk,他们告诉你使用命名函数而不是运算符。 与流行的看法相反,重载运算符几乎总是错误的,因为它几乎永远不会增加代码的清晰度。令人惊讶的是,例外情况很少。其中包括流输入和输出运算符以及算术运算符(如果您实现类似数字的类型)。 (在教你操作符重载的书之外,这种可能性有多大?)请注意,有些人对 std lib 重载 + 皱眉(当然还有 +=)对于 std::string 出于同样的原因(以及其他原因,例如 a+b==b+a 适用于数字,但不适用于字符串) - 在我看来,它们确实有道理。

无论如何,如果有人不顾所有建议仍想这样做:
当您尝试调用运算符时,编译器会尝试在调用它的命名空间、所有封闭命名空间以及所有参数的命名空间中查找它。 (后者称为参数相关查找或 Koenig 查找。)参数的命名空间是 std,您不得向其中添加重载。因此,只剩下调用运算符的命名空间及其封闭命名空间 - 包括包含所有其他命名空间的全局命名空间 - 以放置运算符因此,

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

哦,我是否提到过您不应该将其实现为重载运算符?

I fully support GMan and sbk who told you to use a named function instead of an operator. Contrary to popular believe, overloading operators is always almost wrong, because it almost never adds clarity to the code. There are surprisingly few exceptions. Among them are the stream input and output operators as well as the arithmetical operators should you implement a number-like type. (And just how likely is that outside of a book teaching you operator overloading?) Note that some people frown upon the std lib overloading + (and +=, of course) for std::string for the same reason (and others, like that a+b==b+a holds for numbers, but not for strings) - and IMO they do have a point.

Anyway if one wanted to do this despite all advice:
When you try to invoke the operator, the compiler tries to find it in the namespace it was invoked in, all enclosing namespaces, and the namespaces of all the arguments. (The latter is called argument-dependent lookup or Koenig lookup.) The namespace of the argument is std, which you must not add an overload to. So that leaves the namespace the operator is invoked in and its enclosing namespaces - including the global namespace, which encloses all others - to put the operator in.

So if you want to implement it despite all warnings, put it in the namespace where it is used in. If it is used in several namespaces, put it into the one that encloses all these. If that's the global namespace, so be it.

Oh, and did I mention you should not implement this as an overloaded operator?

三人与歌 2024-09-07 18:05:46

AFAIK,您可以将重载添加到任何命名空间(除了 std,因为不允许向其中添加新函数),并且可以使用 using 声明使其可见。例如,boost 的分配库就是这样的 有效(请注意介绍性片段;有关标准库中的先例,请查看 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 占用一位,而不是至少一个字符的大小)。

AFAIK, you can add the overload to any namespace (except std, because you are not allowed to add new functions to it), and you'd make it visible with a using declaration. This is how, for example, boost's assign library works (pay attention to the introductory snippets; for a precedent in the standard library, check out rel_ops). Also note that you can restrict the scope of using declarations, so as to avoid global pollution.

Example, using boost::array because of an old compiler:

#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;
}

I concur that overloading this operator might be somewhat questionable. It's also unclear to me why you don't use std::bitset which overloads this operator with potentially better performance possible because of a more compact internal representation (each bool taking one bit, instead of at least the size of a char).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文