0

The code in the link below doesn't work as intended. I don't know what I'm doing wrong. https://coliru.stacked-crooked.com/a/f6ac59c7c20be10c

The code can be seen below, and the error message is in the link above.

#include <iostream>
#include <string>

namespace Logger
{
    struct IStringable
    {
        virtual ~IStringable() {}
        virtual std::string ToString() const = 0;
    };

    std::string to_string(IStringable const& v) { return v.ToString(); }
    std::string to_string(const char* const& v) { return std::string(v); }

    template<class T>
    void log(T const& v)
    {
        using std::to_string;
        std::cout << "debug: " << to_string(v) << '\n';
    }
}

class Person : public Logger::IStringable {
public:
    Person(const std::string name) : _name(name) { }
    virtual std::string ToString() const { return _name; }
private:
    std::string _name;
};

int main()
{
    Person p("Alice");
    double d = 0.0;
    const char* c = "Some words";

    Logger::log(p); // Works
    Logger::log(d); // Works
    Logger::log(c); // Error

}

 

g++ -std=c++17 -O2 -Wall -Wextra -Werror -pedantic main.cpp && ./a.out
main.cpp: In instantiation of 'void Logger::log(const T&) [with T = const char*]':
main.cpp:39:18:   required from here
main.cpp:19:44: error: no matching function for call to 'to_string(const char* const&)'
         std::cout << "debug: " << to_string(v) << '\n';
                                   ~~~~~~~~~^~~
songyuanyao
  • 169,198
  • 16
  • 310
  • 405
Guy Simonsen
  • 123
  • 5

2 Answers2

4

With the usage of using std::to_string; inside the function body, the names to_string in the namespace Logger won't be found by name lookup; which will stop when find the name in the function scope and no further scope is examined.

Note that for IStringable to_string(IStringable const& v) could be found by ADL, which doesn't work for built-in types like const char*.

1) For arguments of fundamental type, the associated set of namespaces and classes is empty

You can move using std::to_string; out of the function body. e.g.

using std::to_string;
template<class T>
void log(T const& v)
{
    std::cout << "debug: " << to_string(v) << '\n';
}

LIVE

songyuanyao
  • 169,198
  • 16
  • 310
  • 405
2

You can add another using declaration for the Logger namespace to resolve the issue:

template<class T>
void log(T const& v)
{
    using std::to_string;
    using Logger::to_string;

    // now use to_string...
}

The first using std::to_string is too invasive without the second - it causes the name lookup to terminate too early.

lubgr
  • 37,368
  • 3
  • 66
  • 117
  • 2
    You know, that's why I posted an answer in the first place :) – lubgr Jun 06 '19 at 11:12
  • But I don't understand what the error is. If I were to remove the `Logger:log(c)` the code would compile just fine, even when `Logger::log(p)` is still used – Guy Simonsen Jun 06 '19 at 11:12