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;
}