Mike Glaz
Mike Glaz

Reputation: 5392

Can I template operator overloading for operator<<

I have these two overloaded operator<< functions. Can I use the template system to condense these to 1 function?

std::ostream& operator<<(std::ostream& os, const std::vector<glm::vec3>& vertices){
  for (auto i = vertices.begin(); i != vertices.end(); ++i){
    os << glm::to_string(*i) << '\n';
  }

  return os;
}

std::ostream& operator<<(std::ostream& os, const std::vector<glm::ivec3>& vertices){
  for (auto i = vertices.begin(); i != vertices.end(); ++i){
    os << glm::to_string(*i) << '\n';
  }

  return os;
}

Upvotes: 0

Views: 293

Answers (1)

Vittorio Romeo
Vittorio Romeo

Reputation: 93304

Yes, you can use a function template and std::enable_if in order to have a single function which works with both glm::vec3 and glm::ivec3:

template <typename T>
auto operator<<(std::ostream& os, const std::vector<T>& vertices)
    -> std::enable_if_t<
            std::is_same<T, glm::vec3>::value || std::is_same<T, glm::ivec3>::value,
            std::ostream&>
{
  for (auto i = vertices.begin(); i != vertices.end(); ++i){
    os << glm::to_string(*i) << '\n';
  }

  return os;
}

live wandbox example


If you want to instead support every type that works with glm::to_string, you can use expression SFINAE:

template <typename T>
auto operator<<(std::ostream& os, const std::vector<T>& vertices)
    -> decltype(glm::to_string(std::declval<T>()), std::declval<std::ostream&>())
{ 
    // ... as before
}

live wandbox example

Upvotes: 2

Related Questions