带有取消引用类型双关指针的 stof()/stoi() 将打破严格的别名规则
stof()/stoi() with dereferencing type-punned pointer will break strict-aliasing rules
我有自己的类型
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
使用 stoi(number) aka FaF::string&
在 运行 gcc
和 -Wall -Werror -Wextra
开关时导致此错误:
error: dereferencing type-punned pointer will break strict-aliasing
rules [-Werror=strict-aliasing]
我尝试了很多转换,但没有任何帮助。或多或少 std::string
和 FaF::string
是 来自内存分配器的相同类型 apart。
我的问题:如何使用 stoi()/stof()
函数解决此问题?
Update:: 是的,当然,我可以使用 atoi( number.c_str() )
但我想了解这里的问题。
改用c_str
和atoi:
FaF::string number("1234");
int result = atoi(number.c_str()); // result == 1234
这是 sto*
class 函数的不幸问题;他们 仅 与 std::string
合作。即使他们不关心你使用的是什么分配器,那仍然是类型的一部分,所以它对 C++ 仍然很重要。您也不能假装使用不同分配器的 basic_string
是 std::string
.
直到 C++17 solves this problem (kinda),您将不得不手动处理它:
stoi({number.data(), number.size()});
您不能将字符串与 sto* 函数一起使用。如果您查看文档 (http://en.cppreference.com/w/cpp/string/basic_string/stol),您会发现该函数的签名恰好采用 std::string。其中
std::string = std::basic_string<char, class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>>
我想提请您注意它使用标准分配器。所以实际上你的字符串与 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();
}
};
用法示例:
FaF::string number( "1435151315" );
std::cout << std::stoi( static_cast< std::string >( number ) );
std::cout << std::atoi( static_cast< const char* >( 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); }
然后很容易编写我自己的 - 更通用 - 版本:
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::string numberFaF( "1234" );
std::string numberStd( "4321" );
printf( "stoi<FaF::string>=%d - stoi<std::string>=%d\n",
FaF::stoi( numberFaF ), FaF::stoi( numberStd ) );
编译并产生预期结果:
stoi<FaF::string>=1234 - stoi<std::string>=4321
我只是想知道为什么还没有通用版本。 STL 中的几乎所有内容都是作为模板实现的,这个简单的函数是 硬编码 到 std::string
...
我有自己的类型
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
使用 stoi(number) aka FaF::string&
在 运行 gcc
和 -Wall -Werror -Wextra
开关时导致此错误:
error: dereferencing type-punned pointer will break strict-aliasing rules [-Werror=strict-aliasing]
我尝试了很多转换,但没有任何帮助。或多或少 std::string
和 FaF::string
是 来自内存分配器的相同类型 apart。
我的问题:如何使用 stoi()/stof()
函数解决此问题?
Update:: 是的,当然,我可以使用 atoi( number.c_str() )
但我想了解这里的问题。
改用c_str
和atoi:
FaF::string number("1234");
int result = atoi(number.c_str()); // result == 1234
这是 sto*
class 函数的不幸问题;他们 仅 与 std::string
合作。即使他们不关心你使用的是什么分配器,那仍然是类型的一部分,所以它对 C++ 仍然很重要。您也不能假装使用不同分配器的 basic_string
是 std::string
.
直到 C++17 solves this problem (kinda),您将不得不手动处理它:
stoi({number.data(), number.size()});
您不能将字符串与 sto* 函数一起使用。如果您查看文档 (http://en.cppreference.com/w/cpp/string/basic_string/stol),您会发现该函数的签名恰好采用 std::string。其中
std::string = std::basic_string<char, class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>>
我想提请您注意它使用标准分配器。所以实际上你的字符串与 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();
}
};
用法示例:
FaF::string number( "1435151315" );
std::cout << std::stoi( static_cast< std::string >( number ) );
std::cout << std::atoi( static_cast< const char* >( 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); }
然后很容易编写我自己的 - 更通用 - 版本:
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::string numberFaF( "1234" );
std::string numberStd( "4321" );
printf( "stoi<FaF::string>=%d - stoi<std::string>=%d\n",
FaF::stoi( numberFaF ), FaF::stoi( numberStd ) );
编译并产生预期结果:
stoi<FaF::string>=1234 - stoi<std::string>=4321
我只是想知道为什么还没有通用版本。 STL 中的几乎所有内容都是作为模板实现的,这个简单的函数是 硬编码 到 std::string
...