是C++标准允许的自定义类型的std::to_string的专用化
Is specialization of std::to_string for custom types allowed by the C++ standard?
在C++11及更高版本中,是否允许在std
命名空间中为自定义类型专门化std::to_string
?
namespace std {
string to_string(::MyClass const & c) { return c.toString(); }
}
示例用例:
int main() {
MyClass c;
std::cout << std::to_string(c) << std::endl;
}
在C++11及更高版本中,是否允许在自定义类型的std命名空间中专门化std::to_string?
没有。首先,它不是一个模板函数,所以你根本不能专门化它。
如果你想添加自己的重载函数,答案仍然不变。
扩展命名空间std:的文档片段
向命名空间std或嵌套在std中的任何命名空间添加声明或定义是未定义的行为,下面指出了一些例外
只有当声明依赖于用户定义的类型并且专门化满足原始模板的所有要求时,才允许将任何标准库模板的模板专门化添加到命名空间std,除非禁止此类专门化。
在实践中,一切可能都会很好,但严格来说,标准规定不能保证会发生什么。
编辑:我无法访问官方标准,因此以下内容来自免费工作草案(N4296):
17.6.4.2命名空间使用
17.6.4.2.1命名空间标准
- 如果C++程序将声明或定义添加到命名空间std或命名空间std中的命名空间,除非另有指定。程序可以添加模板专用化对于任何标准库模板,仅当声明依赖于用户定义的类型时,才将其命名为std并且专业化满足原始模板的标准库要求,并且没有明确禁止181
如果C++程序声明,则其行为是未定义的
2.1——标准库类模板或的任何成员函数的显式专门化
2.2——标准库类或类模板的任何成员函数模板的显式专门化,或
2.3——标准库类或类的任何成员类模板的显式或部分专用化样板
只有当声明取决于用户定义类型的名称,并且实例化满足标准库要求用于原始模板。
- 翻译单元不应将命名空间std声明为内联命名空间(7.3.1)
如果我没有弄错,您可以简单地为泛型类型重载to_string
:
template<typename T> to_string(const T& _x) {
return _x.toString();
}
这允许您的程序使用ADL(自变量相关查找),根据传递的类型正确选择相关的CCD_ 4方法。
在C++11及更高版本中,是否允许在自定义类型的std命名空间中专门化std::to_string?
不可以,不能将重载添加到to_string()
的std
命名空间中。
好消息是你不需要,有一个简单的解决方案
您可以提供自己的实现,并让ADL(参数相关查找)为您解决问题。
方法如下:
class A {};
std::string to_string(const A&)
{
return "A()";
}
int main()
{
A a;
using std::to_string;
std::cout << to_string(2) << ' ' << to_string(a);
}
在这里,我们使用using声明将std::to_string
引入作用域,然后使用对to_string()
的非限定调用。
现在std::to_string
和::to_string
都是可见的,编译器会选择适当的重载。
如果你不想在每次使用to_string
之前编写using std::to_string
,或者你担心在没有命名空间的情况下忘记使用to_string
,你可以创建一个帮助函数
template<typename T>
std::string my_to_string(T&& t)
{
using std::to_string;
return to_string(std::forward<T>(t));
}
注意,这个函数可以在任何命名空间中定义,并且与定义类的命名空间无关(它们不必相同)。
请参见示例。
注意:如果您是调用to_string
的人,则此操作有效。如果有一个库调用std::to_string
,而你想根据你的类型更改它,那你就太倒霉了。
如果可能的话,最好创建自己的函数来使用std::to_string
,只要.toString()
方法可用于传递的参数:
#include <type_traits>
#include <iostream>
#include <string>
struct MyClass {
std::string toString() const { return "MyClass"; }
};
template<class T>
typename std::enable_if<std::is_same<decltype(std::declval<const T&>().toString()), std::string>::value, std::string>::type my_to_string(const T &t) {
return t.toString();
}
template<class T>
typename std::enable_if<std::is_same<decltype(std::to_string(std::declval<T&>())), std::string>::value, std::string>::type my_to_string(const T &t) {
return std::to_string(t);
}
int main() {
std::cout << my_to_string(MyClass()) << std::endl; // will invoke .toString
std::cout << my_to_string(1) << std::endl; //will invoke std::to_string
}
- C++:如何将 unix 时间的字符串转换为 *tm?(使用时间错误:"cannot convert 'String' to 'tm*' ")
- OpenCV undefined reference to 'cv::imread(cv::String const&, int)'
- std::time_point from and to std::string
- "No suitable conversion function from 'std::string' to 'const char *' exists"
- 如果子类中没有构造函数方法,则错误"no matching function for call to 'LGame::LGame(String&)'"
- 使用词法强制转换在'string to double'中设置双精度变量的精度
- 在 Lua 中加载 C++ 模块时'Attempt to index a string value'错误
- std::string to std::regex
- "How to pass String value in between URL in C/C++?"
- "conversion from void to non scalar type string"是什么意思?
- 我收到一个" conversion from ‘std::string (*)[50]’ to non-scalar type ‘std::string’ requested"错误,似乎无法修复它
- 如何防止从函数生成的字符串中使用科学记数法"number to string"?
- hwProfileInfo.szHwProfileGuid to String?
- 编写我自己的字符串类"reference to ‘string’ is ambiguous"但出现编译错误
- c++ stringstream to ostream to string
- How cin to string?
- C++ *string convert to string
- Round Double and Cast to String
- Regex-ed value to String
- vector string to string (or c_string) to lpszString