C++ 带有取消引用类型双关指针的stof()/stoi()将打破严格的别名规则
我有自己的类型C++ 带有取消引用类型双关指针的stof()/stoi()将打破严格的别名规则,c++,casting,stl,std,C++,Casting,Stl,Std,我有自己的类型 namespace FaF { // Allocator is my own Memory Allocator for STL using string = std::basic_string<char, std::char_traits<char>, Allocator<char>>; } FaF::string number("1234"); stoi( (const std::string &) number);
namespace FaF
{
// Allocator is my own Memory Allocator for STL
using string = std::basic_string<char, std::char_traits<char>, Allocator<char>>;
}
FaF::string number("1234");
stoi( (const std::string &) number); <-- error
名称空间FaF
{
//分配器是我自己的STL内存分配器
使用string=std::basic_字符串;
}
FaF::字符串编号(“1234”);
stoi((const std::string&)编号) 使用c_str
和atoi代替:
FaF::string number("1234");
int result = atoi(number.c_str()); // result == 1234
这是sto*
函数类的一个不幸问题;它们仅适用于std::string
。即使他们不关心你使用的分配器,但仍然是类型的一部分,所以它仍然对C++重要。您也不能假装使用不同分配器的basic_string
是std::string
在C++17之前,您必须手动处理它:
stoi({number.data(), number.size()});
不能将字符串与sto*函数一起使用。如果您查看docs(),您会发现函数的签名正好是std::string。在哪里
std::string = std::basic_string<char, class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>>
std::string=std::basic\u string
我想提醒您注意,它使用标准分配器。因此,实际上您的字符串与std::string不同
作为一种解决方法,您可以指定std::string运算符
struct string : public std::basic_string<char, std::char_traits<char>, Allocator<char>>
{
// will produce a copy. use const char* instead
explicit operator std::string()
{
return c_str();
}
explicit operator const char*()
{
return c_str();
}
};
结构字符串:公共标准::基本字符串
{
//将生成一个副本。请改用常量字符*
显式运算符std::string()
{
返回c_str();
}
显式运算符const char*()
{
返回c_str();
}
};
用法示例:
FaF::string number( "1435151315" );
std::cout << std::stoi( static_cast< std::string >( number ) );
std::cout << std::atoi( static_cast< const char* >( number ) );
FaF::字符串编号(“14351315”);
std::cout(number));
std::cout(number));
PS:不要使用C样式转换!:)
我希望它能有所帮助。在学习了basic_string.h
中std::stoi
的定义之后:
inline int
stoi(const string& __str, size_t* __idx = 0, int __base = 10)
{ return __gnu_cxx::__stoa<long, int>(&std::strtol, "stoi", __str.c_str(),
__idx, __base); }
inline int
stoi(常量字符串和字符串,大小\u t*\u idx=0,整数\u基数=10)
{return uu gnu cxx::u stoa(&std::strtol,“stoi”,uu str.c_str(),
__idx,_基);}
然后,我就很容易编写自己的——更一般的——版本:
namespace FaF
{
template<typename T>
inline int
stoi(const T& __str, size_t* __idx = 0, int __base = 10)
{ return __gnu_cxx::__stoa<long, int>(&std::strtol, "stoi", __str.c_str(),
__idx, __base); }
}
名称空间FaF
{
模板
内联整数
stoi(常数T和常数str,大小T*\UUUIdx=0,整数基数=10)
{return uu gnu cxx::u stoa(&std::strtol,“stoi”,uu str.c_str(),
__idx,_基);}
}
这个测试脚本
FaF::string numberFaF( "1234" );
std::string numberStd( "4321" );
printf( "stoi<FaF::string>=%d - stoi<std::string>=%d\n",
FaF::stoi( numberFaF ), FaF::stoi( numberStd ) );
FaF::字符串numberFaF(“1234”);
std::字符串编号std(“4321”);
printf(“stoi=%d-stoi=%d\n”,
FaF::stoi(numberFaF),FaF::stoi(numberStd));
编译并生成预期结果:
stoi<FaF::string>=1234 - stoi<std::string>=4321
stoi=1234-stoi=4321
我只是想知道为什么还没有一个通用的版本。STL中的几乎所有内容都是作为模板实现的,这个简单的函数被硬编码为
std::string
…关键在于:这两种类型不一样,句号。你不能把一个抛给另一个。这不仅仅是一个理论问题,例如,sizeof(std::allocator)!=sizeof(您的::分配器)
@erenon好的,这意味着我必须编写自己版本的stoi()/stof()
,比如FaF::stoi()/FaF::stof()
?作为替代,您也可以将字符串复制到常规字符串中。@erenon是的,我在考虑这个问题,但我认为最好将它封装到我自己的名称空间
和函数
“然后就可以很容易地编写我自己的更通用的版本:”它只在一个实现上工作,因为你调用的是非标准函数。@Nicolas??我不明白。它完全是gcc提供的basic_string.h
的副本-只需将其包装到模板中即可;这就是问题所在。它只适用于GCC<代码>\uuuu gnu\ucxx不存在于,例如libc++.@nicolas:-);我现在抓到你了。由于环境的原因,我和gcc结婚了。这是一个非常特殊的项目,不会部署在其他系统上。到目前为止,对我来说还可以。谢谢你指出这一点!你能简要总结一下C++17是如何解决这个问题的吗?C++17的代码段是什么?