g++, проблема переопределения компиляции оператора ostream << std::array с шаблоном

Я не могу скомпилировать с помощью g++ простой код, который отлично работает в MSVC.

Код включает перегрузку оператора для ostream << array<T,D>, и g++ не может его найти, хотя он находится прямо здесь. При этом аналогичная перегрузка для ostream << vector не вызывает проблем для g++.

Демо:

      #include <iostream>
#include <vector>
#include <array>

template <class T> inline std::ostream& operator << (std::ostream& os, std::vector<T> &v) {
    const int D = v.size();
    os << "[";
    if (D > 0) os << v[0];
    for (int i = 1; i < D; i++) os << "," << v[i];
    os << "]";
    return os;
};

template <class T, int D> std::ostream& operator << (std::ostream& os, std::array<T, D> &a) {
    os << "[";
    if (D > 0) os << a[0];
    for (int i = 1; i < D; i++) os << "," << a[i];
    os << "]";
    return os;
};


int main() {
    std::vector<double> v = {1,2,3,4};
    std::cout << v << std::endl;

    //std::array<double, 2> a = { 1,2 };            <-- this lines won't compile in g++
    //std::cout << a << std::endl;

    return 0;
}

Закомментированные строки заставляют g++ выдавать огромный список жалоб, начиная с

      test.cpp:33:12: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream<char>'} and 'std::array<double, 2>')
   33 |  std::cout << a << std::endl;
      |  ~~~~~~~~~ ^~ ~
      |       |       |
      |       |       std::array<double, 2>
      |       std::ostream {aka std::basic_ostream<char>}

и заканчивая

      ostream:691:5: error: no type named 'type' in 'struct std::enable_if<false, std::basic_ostream<char>&>'

Версия g++

      g++.exe (Rev2, Built by MSYS2 project) 9.2.0
Copyright (C) 2019 Free Software Foundation, Inc.

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

Почему так и как решить?

Мне нужен код, скомпилированный g++, потому что в нем есть __float128. И мне нужны шаблоны, потому что это часть обобщенного алгоритма.

Обратите внимание, что я новичок в C++.

Я искал похожие случаи, но ничего не нашел, по крайней мере, ничего полезного.

2 ответа

Нетиповой аргумент шаблонаstd::arrayимеет типsize_tнетint.

Я не уверен, какой компилятор здесь правильный, но gcc принимает код, если вы это исправите:

      template <class T, size_t D> std::ostream& operator << (std::ostream& os, std::array<T, D> &a) {
    os << "[";
    if (D > 0) os << a[0];
    for (int i = 1; i < D; i++) os << "," << a[i];
    os << "]";
    return os;
};

Полный пример

PS: Обратите внимание, что перегрузка<<для типов, которыми вы не владеете, есть определенные оговорки. Шаблон функцииtemplate <typename T,size_t D> void print(const std::array<T,D>&)может сделать печать, а также.

Проблема в том, что нетиповой параметр в вашей перегруженной версии имеет тип, а неstd::size_t.

Чтобы решить эту проблему, вы можете изменить параметр, не являющийся типомDбыть типаsize_tвместоintкак показано ниже:

      //-----------------vvvvvvvvvvv---->changed int to std::size_t
template <class T, std::size_t D> std::ostream& operator << (std::ostream& os, std::array<T, D> &a) {
    os << "[";
    if (D > 0) os << a[0];
    for (int i = 1; i < D; i++) os << "," << a[i];
    os << "]";
    return os;
};


int main() {
   
    std::array<double, 2> a = { 1,2 };        
    std::cout << a << std::endl;  //works with all compiler now

    return 0;
}

Рабочая демонстрация

Другие вопросы по тегам