Where to add the overloaded operator for tr1 :: array?

Since I need to add operator&

for 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 which namespace I should put this function in. I viewed the namespace std

as a bounded scope. The user can add only general specialization and overloaded function templates. Putting it in the global namespace is not "permitted" to prevent pollution of the global namespace and collisions with other declarations. And finally, putting this feature in the project's namespace doesn't work as the compiler won't find it there.

What is the best thing for me to do? I don't want to write a new array class put into the project namespace. Because in this case, the compiler will find the correct namespace using a name-dependent lookup. Or is this the only possible way, since writing a new operator for existing classes means extending their interfaces, and this is not allowed for standard classes?

+2


a source to share


2 answers


I fully support GMan and sbk who told you to use a named function instead of an operator. Contrary to popular belief, overloading operators are almost always wrong because they almost never add clarity to your code. There are surprisingly few exceptions. These include stream input and output operators, and arithmetic operators if you implement a numeric type. (And how likely is it that, outside of the book, teaching you operator overloading?) Note that some people are unhappy with std lib overloading +

(and of +=

course) for std::string

the same reason (and others, as if it a+b==b+a

works for numbers, but not for strings ) - and IMO they have a point.

Anyway, if someone wanted to do this, despite all the advice:
When you try to invoke a statement, the compiler tries to find it in the namespace in which it was called, all the encompassing namespaces and namespaces of all arguments. (The latter is called argument-dependent lookup or Koenig lookup.) Argument namespace std

you shouldn't add overload to. So this leaves the namespace that the statement runs in and its enclosing namespaces - including the global namespace that spans all the others - to put the statement in.



So, if you want to implement it despite all the warnings, put it in the namespace where it is used. If it is used in multiple namespaces, place it in one that covers all of them. If it's a global namespace, so be it.

Oh, and did I mention that you shouldn't be implementing this as an overloaded operator?

+7


a source


AFAIK, you can add an overload to any namespace (except std, because you are not allowed to add new functions to it), and you can make it visible with a using declaration. So, for example, boosting library assignment works (note the introductory snippets, for use case in the standard library check rel_ops ). Also note that you can limit the scope of declarations to avoid global pollution.

Example using boost::array

because of the 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 agree that overloading this operator can be somewhat questionable. It is also not clear to me why you are not using std::bitset

that overloads this operator with potentially better performance due to a more compact internal representation (each bool takes one bit, not at least the size of a char).

+1


a source







All Articles