16

The title says it all really. Why did they choose to not have a

namespace std
{
    std::string to_string(const std::string&)
}

overload?

I have an program that can query some data by row index or row name; ideal for templates. Until I try to construct an error message if a row being accessed is missing:

template <typename T>
int read(T nameOrIndex)
{
    if (!present(nameOrIndex))
    {
        // This does not compile if T is std::string.
        throw std::invalid_argument("Missing row: " + std::to_string(nameOrIndex));
    }
}

I could add my own overload to the std namespace but that's not ideal.

5
  • 3
    It's probably just missing due to oversight. Commented Apr 12, 2016 at 22:30
  • 4
    Your code will not compile if T is any number of other types too. What about all of those? Should there be a to_string implementation that returns some string for arbitrary types? Instead of adding to_string overloads to std (which is illegal), I'd create my own to_string overloads in the same namespace as read. Delegate to std::to_string from that, and return the argument as is from the overload that takes std::string const&. Commented Apr 12, 2016 at 22:43
  • 2
    std::to_string converts built-in numeric types to strings. There's no corresponding need to "convert" strings to strings because they already are strings. Commented Apr 12, 2016 at 23:35
  • As I understand, to_string is basically a safe interface to the C formatting utilities that conceals the buffer and all that from you. There is a C formatting specifier %s for strings. Thus, something has clearly been lost :) Commented Jun 21, 2016 at 11:28
  • @PeteBecker: It would add consistency and potentially ease some code. Despite a lack of need, you can also convert an integer to an integer, e.g. int x; int y = static_cast<int>(x);. Commented Oct 16, 2018 at 8:40

2 Answers 2

13

Rather than define your own overload taking std::string in the std namespace, which is a very bad solution, just do this instead:

#include <iostream>
#include <string>

std::string to_string(const std::string& value)
{
    return value;
}

template <typename T>
void display(T value)
{
    using namespace std;
    std::cout << to_string(value) << std::endl;
}

int main()
{
    display("ABC");
    display(7);
}
Sign up to request clarification or add additional context in comments.

3 Comments

This code doesn't use ADL, because the arguments have builtin type. Instead, the display function brings in names from std, so that unqualified lookup has both std::to_string and ::to_string in the lookup set.
@M.M, what does ADL mean in this context?
I remember that "using namespace" is not a good practice for embedded software, according to AUTOSAR. I don't have the exact rule though.
2

I'm not going to guess why the overload is not in the standard library but here is a simple solution you can use. Instead of std::to_string, use boost::lexical_cast.

template <typename T>
int read(T nameOrIndex)
{
  if (!present(nameOrIndex))
    {
      throw std::invalid_argument {
          "Missing row: " + boost::lexical_cast<std::string>(nameOrIndex)
      };
    }
  // …
}

If you don't want the Boost dependency, you can easily roll your own function for this.

template <typename T>
std::string
to_string(const T& obj)
{
  std::ostringstream oss {};
  oss << obj;
  return oss.str();
}

It is obviously not optimized but might be good enough for your case.

1 Comment

ostringstream is definitely the most cross-type solution. It fixes the weird fact that std::to_string doesn't work for std::string arg

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.