Search code examples
c++g++operator-overloadingc++-templates

g++, compilation problem overriding operator ostream << std::array with template


I cannot compile with g++ a simple code that works perfectly in MSVC.

The code involves operator overload for ostream << array<T,D>, and g++ cannot find it, even though it's right here. Wherein the similar overload for ostream << vector doesn't cause any problem for g++.

A demo:

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

The commented lines cause g++ to spit a huge list of complains, starting with

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

and ending with

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

The g++ version is

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

The same story is with other operators, but I left only the essential part.

Why is that and how to solve?

I need the code compiled by g++, because in has __float128. And I need the templates, because it's a part of generalized algorithm.

Please note that I'm new to C++.

I searched for similar cases but didn't any, at least not something helpful.


Solution

  • The non-type template argument of std::array is of type size_t not int.

    I am not sure which compiler is right here, but gcc accepts the code if you fix that:

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

    Complete Example

    PS: Note that overloading << for types you do not own comes with certain caveats. A function template template <typename T,size_t D> void print(const std::array<T,D>&) can do the printing as well.