使用 const char * 时如何将记录器与模板一起使用?
How to use logger with template when using const char *?
下面 link 中的代码无法正常工作。我不知道我做错了什么。
https://coliru.stacked-crooked.com/a/f6ac59c7c20be10c
代码可以看下面,报错信息在上面link
#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';
~~~~~~~~~^~~
您可以为 Logger
命名空间添加另一个 using 声明来解决问题:
template<class T>
void log(T const& v)
{
using std::to_string;
using Logger::to_string;
// now use to_string...
}
如果没有第二个,第一个 using std::to_string
太具有侵略性 - 它会导致名称查找过早终止。
在函数体内使用using std::to_string;
,命名空间Logger
中的名称to_string
将不会被name lookup找到;当在函数范围内找到名称并且没有进一步检查范围时,它将停止。
请注意,对于 IStringable
to_string(IStringable const& v)
可以通过 ADL 找到,这不适用于 built-in 类型,例如 const char*
.
1) For arguments of fundamental type, the associated set of namespaces and classes is empty
您可以将 using std::to_string;
移出函数体。例如
using std::to_string;
template<class T>
void log(T const& v)
{
std::cout << "debug: " << to_string(v) << '\n';
}
下面 link 中的代码无法正常工作。我不知道我做错了什么。 https://coliru.stacked-crooked.com/a/f6ac59c7c20be10c
代码可以看下面,报错信息在上面link
#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';
~~~~~~~~~^~~
您可以为 Logger
命名空间添加另一个 using 声明来解决问题:
template<class T>
void log(T const& v)
{
using std::to_string;
using Logger::to_string;
// now use to_string...
}
如果没有第二个,第一个 using std::to_string
太具有侵略性 - 它会导致名称查找过早终止。
在函数体内使用using std::to_string;
,命名空间Logger
中的名称to_string
将不会被name lookup找到;当在函数范围内找到名称并且没有进一步检查范围时,它将停止。
请注意,对于 IStringable
to_string(IStringable const& v)
可以通过 ADL 找到,这不适用于 built-in 类型,例如 const char*
.
1) For arguments of fundamental type, the associated set of namespaces and classes is empty
您可以将 using std::to_string;
移出函数体。例如
using std::to_string;
template<class T>
void log(T const& v)
{
std::cout << "debug: " << to_string(v) << '\n';
}