10
votes

The following code gives a compiler error (gcc-4.7 run with -std=c++11):

#include <iostream>
#include <array>

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

int main() {
  std::array<double, 2> lower{1.0, 1.0};
  std::cout << lower << std::endl;
  return 0;
}

Error message:

tmp6.cpp: In function ‘int main()’: tmp6.cpp:16:16: error: cannot bind
‘std::ostream {aka std::basic_ostream}’ lvalue to
‘std::basic_ostream&&’ In file included from
/usr/include/c++/4.7/iostream:40:0,
from tmp6.cpp:1: /usr/include/c++/4.7/ostream:600:5: error: initializing argument 1 of ‘std::basic_ostream<_CharT,
_Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits; _Tp = std::array]’

When I get rid of the template function declaration and replace T with double and N with 2, it compiles just fine (edit: leaving T and replacing N with 2 works, but specifying N=2 as the default argument for N doesn't work.).

  1. Does anyone know why gcc can't automatically bind this?
  2. What would be the syntax for calling the << operator with explicitly specified template parameters?

Answer to question 2: operator<<<double, 2>(std::cout, lower);

Edit: This is also true for the following function, which is only templated in the array size:

template <int N>
void print(const std::array<double, N> & arr) {
  std::cout << "print array here" << std::endl;
}

int main() {
  std::array<double, 2> lower{1.0, 1.0};
  print<2>(lower); // this works
  print(lower);    // this does NOT work
  return 0;
}

Thanks a lot for your help.

2
Note that you shouldn't be defining operator << for a standard type.K-ballo
@K-ballo Any idea how to answer either of the two numbered questions in the post?user
If I could answer, I would have placed an answer instead of a comment... The problem probably comes from implementing operators in a wrong way.K-ballo
@K-ballo The same question could be proposed using a function template <int N> print (const std::array<double, N> & arr) { /*...*/ }. I wonder why gcc can't bind this...user
Do you mean print( lower ); won't compile? Could you add your test case for the print version to your question?K-ballo

2 Answers

13
votes

Consider your declaration:

template <typename T, int N>
std::ostream & operator <<(std::ostream & os, const std::array<T, N> & arr) {

The definition for std::array is:

template<typename T, std::size_t N> class array {...};

You are using int instead of std::size_t, and that's why it doesn't match.

1
votes

You can call operator<< with specified template parameters in this, not so aestethic, way:

operator<< <double,2>(std::cout, lower) << std::endl;