Предположим, у меня есть следующий Data
класс:
struct Data {
char foo[8];
char bar;
};
и следующая функция my_algorithm
, которая принимает пару char *
(аналогично алгоритму STL):
void my_algorithm(char *first, char *last);
Для Data
foo
члена данных вместо вызова my_algorithm()
, например:
Data data;
my_algorithm(data.foo, data.foo + 8);
Я могу использовать шаблоны удобных функций std::begin()
и std::end()
:
my_algorithm(std::begin(data.foo), std::end(data.foo));
Я бы хотел достичь чего-то похожего на Data
элемент данных *1025*. То есть вместо того, чтобы писать:
my_algorithm(&data.bar, &data.bar + 1);
Я хотел бы написать что-то вроде:
my_algorithm(begin(data.bar), end(data.bar));
Поэтому для этого случая я определил две следующие обычные (не шаблонные) функции:
char* begin(char& c) { return &c; }
char* end(char& c) { return &c + 1; }
Чтобы я мог написать код, подобный следующему:
Data data;
using std::begin;
using std::end;
my_algorithm(begin(data.foo), end(data.foo)); // ok - std::begin()/std::end()
my_algorithm(begin(data.bar), end(data.bar)); // Error!!!
При объявлении using
выше я бы ожидал, что std::begin()
/ std::end()
и ::begin()
/ ::end()
будут находиться в одном и том же наборе перегрузки соответственно. Так как функции ::begin()
и ::end()
идеально подходят для последнего вызова и не являются шаблонами, я ожидал, что последний вызов my_algorithm()
будет соответствовать им. Однако обычные функции вообще не рассматриваются. В результате компиляция не удалась, потому что std::begin()
и std::end()
не совпадают для вызова.
По сути, последний вызов действует так, как если бы я написал вместо этого:
my_algorithm(begin<>(data.bar), end<>(data.bar));
То есть, в процессе разрешения перегрузки рассматриваются только шаблоны функций (т.е. std::begin()
/ std::end()
), а не обычные функции (т.е. не ::begin()
/ ::end()
).
Это работает только так, как и ожидалось, если я полностью квалифицирую звонки на ::begin()
/ ::end()
:
my_algorithm(::begin(data.bar), ::end(data.bar));
Что мне здесь не хватает?