带有解除引用类型惩罚指针的stof()/ stoi()将破坏严格别名规则

时间:2016-06-23 19:47:31

标签: 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);  <-- error
使用stoi(number) aka FaF::string&时,使用gcc运行-Wall -Werror -Wextra会导致此错误:

  

错误:解除引用类型惩罚指针将破坏严格别名   规则[-Werror = strict-aliasing]

我尝试了很多铸件,但没有任何帮助。或多或少std::stringFaF::string 与内存分配器中的相同

我的问题:如何使用stoi()/stof()函数解决此问题?

更新:: 是的,当然,我可以使用atoi( number.c_str() ),但我想了解此处的问题。

4 个答案:

答案 0 :(得分:2)

这是sto*类函数的一个不幸的问题;他们使用std::string。尽管他们并不关心你正在使用的分配器,但它仍然是该类型的一部分,所以它对C ++仍然很重要。你也不能假装使用不同分配器的basic_stringstd::string

直到C ++ 17 solves this problem (kinda),你必须手动处理它:

stoi({number.data(), number.size()});

答案 1 :(得分:1)

使用c_str和atoi代替:

FaF::string number("1234");
int result = atoi(number.c_str()); // result == 1234

答案 2 :(得分:0)

您不能将字符串与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 operator。

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风格的演员阵容! :)

我希望它有所帮助。

答案 3 :(得分:0)

学习 std::stoi中对basic_string.h的定义后

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 ......