Для 1 это выглядит следующим образом:
namespace printing {
template<class T>
void print(std::ostream& os, T const& t){
os<<t;
}
template<class It>
void print_range( std::ostream& os, It b, It e );
template<class T,std::size_t N>
void print( std::ostream& os, T const(&arr)[N] ){
print_range(os, std::begin(arr), std::end(arr) );
}
template<class T,std::size_t N>
void print( std::ostream& os, std::array<T, N> const& arr ){
print_range(os, std::begin(arr), std::end(arr) );
}
template<class T, class A>
void print( std::ostream& os, std::vector<T, A> const& arr ){
print_range(os, std::begin(arr), std::end(arr) );
}
// etc
template<class It>
void print_range( std::ostream& os, It b, It e ){
for(auto it=b; it!=e; ++it)
print(os, *it);
}
}
, чтобы улучшить добавление обнаружения итерации SFINAE вместо отдельных перегрузок.
Для 2 запишите определение SFINAE для .print(std::ostream&)
метод для обоих типов указателей и экземпляров (через decltype и ->
и .
).Затем напишите print
перегрузку, которая работает только для ->print
и .print
-безопасных типов, и она будет лучше соответствовать версии os<<t;
, но хуже, чем любая свободная функция print
в пространстве имен типа.
Правильное выполнение занимает несколько десятков строк шаблонного шаблона, и я бы хотел несколько раз проверить порядок перегрузки в реальном компиляторе.В конце концов os<<t
функция, вероятно, не будет вызываться print
или не будет находиться в не детализированном пространстве имен.