THND
THND

Reputation: 217

How to compile programm with error "no matching function for call to 'to_string'"? c++

If I have here DATA_T = std::string, I can't compile this code, because of error "no matching function for call to 'to_string'". The function does not allow converting a string to a string. But I need to get the string anyway, how can I work around this error and compile the program?

template <typename DATA_T>
std::string get_string(DATA_T subdata) {
  std::string data = "...";
  if (typeid(subdata) == typeid(std::string))
    data += subdata;
  else
    data += std::to_string(subdata);
  return data;
}

Upvotes: 4

Views: 1751

Answers (3)

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122133

As shown in other answers you can add a special case for std::string. This will solve your problem with std::string, but how about other types?

When I first saw to_string I was rather disappointed, because it has only a finite set of overloads. However, I misunderstood what to_string is meant for. It is meant to convert to string exactly as std::sprintf would do with the right format specifier. As sprintf is inherited from C, it cannot convert all types to string that you can convert to string in C++. There is no way to enable conversion of custom types via sprintf directly. And because of that, to_string has the same limitations. In particular there is no to_string(const std::string&).

Overloading std::ostream& operator<<(std::ostream&,const T&) is more flexible. You want to call get_string with a foo or a bar? Why not:

#include <iostream>
#include <sstream>

template <typename DATA_T>
std::string get_string(DATA_T subdata) {
    std::stringstream data;
    data << "...";
    data << subdata;
    return data.str();
}

struct foo {};

std::ostream& operator<<(std::ostream& out,const foo& f){
    return out << "foo";
}

int main() {
    foo f;
    std::cout << get_string(f);
}

If you actually do want to convert like sprintf does, I'd probably stay with one of the solutions presented in the other answers.

Upvotes: 4

Nathan Pierson
Nathan Pierson

Reputation: 5565

Instead of trying to branch on the type of a template argument inside the body of your function, you can write an overload that will be preferred when the argument is a std::string.

template <typename DATA_T>
std::string get_string(DATA_T subdata) {
  std::string data = "...";
  data += std::to_string(subdata);
  return data;
}

std::string get_string(std::string subdata)
{
  std::string data = "...";
  data += subdata;
  return data;
}

Upvotes: 11

Yksisarvinen
Yksisarvinen

Reputation: 22176

With C++17 it can be made simpler using if constexpr:

#include <string>
#include <type_traits>

template <typename DATA_T>
std::string get_string(DATA_T subdata) {
  std::string data = "...";
  if constexpr (std::is_same_v<DATA_T, std::string>)
    data += subdata;
  else
    data += std::to_string(subdata);
  return data;
}

See the other answer for a pre-C++17 solution.

Upvotes: 11

Related Questions