HEKTO
HEKTO

Reputation: 4191

How to overload operator<< to output a vector, defined inside a template?

The example below is a distilled version of a problem with templates I'm having - please see compilation errors below.

#include <iostream>
#include <vector>

template <class T> struct S
{
  typedef std::vector<T> SVec;
};

template <class T> std::ostream& operator<<(std::ostream& OS, const S<T>::SVec& X)
{
  for (const auto& e: X) OS << e << ' ';
  return OS;
}

int main()
{
  S<int>::SVec v;
  std::cout << v << std::endl;
}

Compiler output:

g++ -g -Wall -O4 -std=c++11 -c tc041.cpp
tc041.cpp:22:69: error: need ‘typename’ before ‘S<T>::SVec’ because ‘S<T>’ is a dependent scope
 template <class T> std::ostream& operator<<(std::ostream& OS, const S<T>::SVec& X)

And so on - hundreds of lines. My compiler - g++ 5.2.1, OS - Xubuntu 4.2.0.

How to make this operator to be compiled correctly?

Upvotes: 3

Views: 386

Answers (1)

user2486888
user2486888

Reputation:

There are two problems:

  • Missing typename keyword at the operator declaration.
  • Template type deduction fails in main.

template <class T>
std::ostream& operator<<(std::ostream& OS, const typename S<T>::SVec& X)

A typename keyword should be placed before S<T>::SVec. Due to language rules, the compiler does not know whether SVec is a member type or something else. The typename keyword is to tell the compiler it is a type.

For details of the language rules, you may refer to: http://en.cppreference.com/w/cpp/language/dependent_name


(Note: I am actually less sure about it because this scenario is new to me too.)

Let's do an experiment. Instead of invoking operator<< with operator syntax, let's invoke it with function syntax.

operator<< (std::cout, v);

Well, it still fails.

What if we invoke it with explicit template argument?

operator<< <int> (std::cout, v);

It works! Well, actually, may work. I find that some standard library header may contain something that interferes it. But let's put it aside.

The problem this experiment demonstrates is that the template argument deduction fails. Argument type of the form class-template-name<T>::member-type cannot be deduced.

Details: http://en.cppreference.com/w/cpp/language/template_argument_deduction

Upvotes: 3

Related Questions