Я использую определение пустого пространства имен, чтобы упростить объявления рекурсивных функций, где одна «сторона» — это перегрузки операторов. Операторы помещаются в свое собственное пространство имен, чтобы разрешить выборочное использование в желаемых областях, а не принудительно использовать, если заголовок включен где-либо (и, таким образом, вызывать ошибки, если разрешения становятся неоднозначными).
Пример:
namespace container_inserters {}
template<class Stream, class Iter, class Ch>
void write_sequence(Stream& s, Iter begin, Iter end,
Ch const *initial, Ch const *sep, Ch const *final)
{
using namespace container_inserters;
if (initial) s << initial;
if (begin != end) {
s << *begin;
++begin;
for (; begin != end; ++begin) {
if (sep) s << sep;
s << *begin;
}
}
if (final) s << final;
}
namespace container_inserters {
#define G(N) \
template<class Ch, class Tr, class T, class A> \
std::basic_ostream<Ch,Tr>& operator<<(std::basic_ostream<Ch,Tr> &s, \
N<T,A> const &value) \
{ \
write_sequence(s, value.begin(), value.end(), "[", ", ", "]"); \
return s; \
}
G(std::deque)
G(std::list)
G(std::vector)
#undef G
} // container_inserters::
Разрешение s << *begin
откладывается до тех пор, пока не будет создан экземпляр write_sequence (поскольку он включает параметры шаблона), к этому моменту оператор уже объявлен и его можно найти с помощью директивы using. Вызов становится рекурсивным для вложенных контейнеров:
int main() {
using namespace std;
vector<deque<list<int> > > v (3, deque<list<int> >(2, list<int>(1, 42)));
using namespace container_inserters;
cout << v << '\n';
return 0;
}
// output:
// [[[42], [42]], [[42], [42]], [[42], [42]]]
У Boost есть похожая библиотека форматирования вывода, но я не знаю, используют ли они ту же технику реализации.
person
Community
schedule
01.10.2010