как перегрузить оператор << для массива в C ++? - PullRequest
6 голосов
/ 16 сентября 2011

Я пытаюсь сделать это так:

template <typename T>
ostream &operator<<(ostream &os, T &arr)
{ /*...*/ }

Но может ли T представлять массив? Правильно ли перегрузить оператор << для массива?


EDIT:

Согласно совету Kerrek SB, вот моя реализация для <<:

template <typename T, unsigned int N>
ostream &operator<<(ostream &os, const T (&arr)[N])
{
    int i;
    for(i = 0; i < N; i++)
        os << arr[i] << " ";
    os << endl;
    return os;
}

Правильно ли реализована моя реализация? Я получил ошибку компиляции.

Ответы [ 2 ]

7 голосов
/ 16 сентября 2011

Вы можете сделать это:

template <typename T, unsigned int N>
std::ostream & operator<<(std::ostream & os, const T (&arr)[N])
{
  // ..
  return os;
}

Конечно, это работает только для массивов времени компиляции. Обратите внимание, что вам не разрешено создавать экземпляры этого шаблона, если T является встроенным типом или типом в пространстве имен std!

Вероятно, лучше сделать это встроенным, если это возможно, так как вы будете вызывать отдельную реализацию для каждого N. (У симпатичного принтера есть пример этого.)

Тем не менее, вы заметите, что общий шаблон вносит неоднозначность, поскольку os << "Hello" теперь имеет две возможные перегрузки: шаблон соответствует const char (&)[6] и (не шаблонная) перегрузка для распада на указатель const char *, которые оба имеют идентичные последовательности преобразования. Мы можем решить эту проблему, отключив нашу перегрузку для массивов символов:

#include <ostream>
#include <type_traits>

template <typename T, unsigned int N>
typename std::enable_if<!std::is_same<T, char>::value, std::ostream &>::type
operator<<(std::ostream & os, const T (&arr)[N])
{
  // ..
  return os;
}

На самом деле, чтобы быть еще более общим, вы можете также сделать параметры шаблона параметров basic_ostream:

template <typename T, unsigned int N, typename CTy, typename CTr>
typename std::enable_if<!std::is_same<T, char>::value,
                        std::basic_ostream<CTy, CTr> &>::type
operator<<(std::basic_ostream<CTy, CTr> & os, const T (&arr)[N])
{
  // ..
  return os;
}

Ввиду того, что T должен быть пользовательским типом, вы можете даже заменить is_same<T, char> на is_fundamental<T>, чтобы получить немного больше проверки (но пользователи по-прежнему не должны использовать это для массивов стандартной библиотеки типов).

3 голосов
/ 16 сентября 2011

Еще один способ сделать это - что-то вроде следующего:

template<typename T>
ostream& operator<<(ostream &out, const std::pair<T, int>& array)
{
    //...code
    return out;
}

Где T будет принимать указатель на массив (т.е. это будет тип указателя, в который будет распадаться массив), а часть пары int будет иметь размер массива. Затем вы можете использовать его следующим образом:

int array[10];
//...some code that initializes array, etc.

cout << make_pair(array, 10);

Один плюс этого метода в том, что он также будет работать для динамических массивов (т. Е. Массивов, которые вы размещаете в куче и т. Д.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...