Почему был изобретен зависимый от аргумента поиск? - PullRequest
9 голосов
/ 25 ноября 2010

Почему был изобретен зависимый от аргумента поиск (ADL)? Просто так мы можем написать cout << stuff вместо std::operator<<(cout, stuff)? Если это так, то почему ADL не ограничивается операторами вместо всех функций?

Можно ли было бы предотвратить внедрение ADL, если бы в C ++ был какой-то другой способ сделать общий вывод как встроенных, так и пользовательских типов, например, безопасных типов printf через шаблоны с переменными числами?

Ответы [ 5 ]

12 голосов
/ 25 ноября 2010

ADL был изобретен для обеспечения принципа интерфейса:

Принцип интерфейса

Для класса X все функции, включая свободные функции, которые оба

  • «упоминание» X и
  • "поставляются с" X

логически являются частью X, потому что они образуют часть интерфейса X.

Проверьте превосходного Херба Саттера Гуру недели по теме.

7 голосов
/ 25 ноября 2010

Если это так, почему ADL не ограничивается операторами вместо всех функций?

Зачем искусственно ограничивать его?ADL может быть сложно реализовать (в сочетании с правилами перегрузки C ++) 1 , но это чрезвычайно полезный метод.Во-первых, тот факт, что он также работает с функциями, значительно упрощает использование других пространств имен без импорта всего пространства имен.

В данном случае библиотека SeqAn :

using seqan::String;
String<Char> url = "http://www.seqan.de/";
std::cout << "The URL " << url << " has length " << length(url) << std::endl;

Обратите внимание, что я использовал функцию seqan::length без указания ее полного имени.ADL все равно находит это.Библиотека SeqAn чрезмерно использует такие функции пространства имен, и префикс каждого использования имени пространства имен будет нецелесообразным.Аналогично, импорт пространства имен часто не рекомендуется.

То же самое, конечно, верно для многих других библиотек, таких как большинство Boost.


1 И я полагаю, что это не было немедленно понято комитетом.

5 голосов
/ 25 ноября 2010

Почему бы не ограничить это операторами?

Давайте рассмотрим простой универсальный алгоритм:

template <typename FwdIt, typename T>
FwdIt remove(FwdIt first, FwdIt last, T const& value)
{
  using std::swap;

  FwdIt result = first;
  for ( ; first != last; ++first)
    if (!(*first == value)) swap(*result++, *first);
  return result;
}

Как это работает с пользовательскими типами и их собственной версией swap? Благодаря ADL .

Это то, что Саттер называет Принцип интерфейса , как упоминал Даниэль.

3 голосов
/ 25 ноября 2010

Это было изобретено, чтобы позволить функцию полиморфизма.Идея состоит в том, что функция, являющаяся глаголом (например, «печать»), имеет только одно значение.Тем не менее, может быть различная реализация в зависимости от того, к чему применяется глагол (например, int, float и std :: string).

Итак, нам нужно одно слово для концепции, но несколько реализаций в зависимости от того, к чему она применяется.

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

Попробуйте написать сложную конкатенацию с помощью printInt (), printString (), printFloat(), вы увидите очевидное многословие.

Другая причина заключается в том, что он позволяет проверить, какая реализация доступна для типа аргумента уступки.Если нет доступной реализации (даже не универсальной - с использованием шаблонов), то компилятор остановит вас, как только сможет, и даст вам понять, что у него нет реализации вашего глагола для данного аргумента.

1 голос
/ 25 ноября 2010

Да, в основном это было придумано для операторов.Но это также дает вам возможность добавлять функции, не являющиеся членами, в интерфейс вашего класса.И это очень мощная вещь, которая мне очень нравится.И это больше не ограничивается операторами.Например, вы можете определить функцию cross_product для вашего класса vector - вы понимаете, что я имею в виду:)

...