Где добавить перегруженный оператор для массива tr1 ::? - PullRequest
2 голосов
/ 10 мая 2010

Поскольку мне нужно добавить 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 ]

7 голосов
/ 10 мая 2010

Я полностью поддерживаю GMan и sbk, которые сказали вам использовать именованную функцию вместо оператора. Вопреки распространенному мнению, перегрузка операторов всегда почти неправильна, потому что она почти никогда не добавляет ясности к коду. Есть удивительно мало исключений. Среди них есть операторы ввода и вывода потока, а также арифметические операторы, если вы реализуете числовой тип. (И насколько вероятно, что за пределами книги, обучающей вас перегрузке операторов?) Обратите внимание, что некоторые люди недовольны перегрузкой std lib ++=, конечно) для std::string по той же причине (и другим , например, a+b==b+a верно для чисел, но не для строк) - и IMO у них есть точка.

В любом случае, если кто-то хотел сделать это, несмотря на все советы:
Когда вы пытаетесь вызвать оператор, компилятор пытается найти его в пространстве имен, которое он вызывал в , во всех включающих пространствах имен и пространствах имен всех аргументов . (Последнее называется поиском, зависящим от аргумента, или поиском Кенига.) Пространство имен аргумента - std, к которому нельзя добавлять перегрузку. Таким образом, из пространства имен оператор вызывается в и его включающих пространства имен - включая глобальное пространство имен , в которое входят все остальные - для помещения оператора.

Поэтому, если вы хотите реализовать его, несмотря на все предупреждения, поместите его в пространство имен, в котором оно используется. Если оно используется в нескольких пространствах имен, поместите его в то, которое охватывает все это. Если это глобальное пространство имен, пусть будет так.

О, и я упоминал, что вы должны не реализовать это как перегруженный оператор?

1 голос
/ 10 мая 2010

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 занимает один бит вместо по крайней мере размера символа). *

...