【发布时间】:2019-04-23 01:19:51
【问题描述】:
我遇到了一些 C++11 std::string 长度的可移植性问题。在 Windows 上是 long long unsigned int,但在 Linux 和 Mac 上是 long unsigned int。我的理解是,使用auto 是解决此类问题的标准方法,但我很难找到一种可移植的方式来通过类接口公开这些属性。
以下类在 Linux GCC 7.3.0(以及 MacOS)上编译和运行没有问题:
g++ -g -O2 -std=c++11 -Werror=conversion stringwrap.cc
./a.out
3
但在 Windows (g++ 8.1.0 MinGW-W64 x86_64-posix-seh-rev0) 上,我得到以下编译错误:
C:\temp\v0.11>g++ -g -O2 -std=c++11 -Werror=conversion stringwrap.cc
In file included from stringwrap.cc:1:
stringwrap.h: In function 'long unsigned int determineFirstPosition(std::__cxx11::string)':
stringwrap.h:35:20: error: conversion from 'std::__cxx11::basic_string<char>::size_type' {aka 'long long unsigned int'}
to 'long unsigned int' may change value [-Werror=conversion]
return s.length();
~~~~~~~~^~
stringwrap.cc: In member function 'long unsigned int Stringwrap::length() const':
stringwrap.cc:9:23: error: conversion from 'std::__cxx11::basic_string<char>::size_type' {aka 'long long unsigned int'}
to 'long unsigned int' may change value [-Werror=conversion]
return str_.length();
~~~~~~~~~~~^~
cc1plus.exe: some warnings being treated as errors
stringwrap.h
#include <iostream>
#include <string>
class Stringwrap
{
private:
std::string str_;
public:
Stringwrap(const std::string& str);
unsigned long int length() const;
unsigned long int getFirstPosition() const;
};
inline unsigned long int determineFirstPosition(const std::string s)
{
for (unsigned long int i = 0; i < s.length(); ++i)
{
switch (s.at(i))
{
case ' ':
{
break;
}
default:
{
return i;
}
}
}
return s.length();
}
stringwrap.cc
#include "stringwrap.h"
Stringwrap::Stringwrap(const std::string& str) : str_(str)
{
}
unsigned long int Stringwrap::length() const
{
return str_.length();
}
unsigned long int Stringwrap::getFirstPosition() const
{
return determineFirstPosition(str_);
}
int main()
{
Stringwrap sw = *new Stringwrap(" x ");
std::cout << sw.getFirstPosition() << std::endl;
}
我尝试将所有unsigned long ints 更改为auto,而-std=c++11 出现以下错误:
C:\temp\v0.11>g++ -g -O2 -std=c++11 -Werror=conversion stringwrap.cc
In file included from stringwrap.cc:1:
stringwrap.h:13:19: error: 'length' function uses 'auto' type specifier without trailing return type
auto length() const;
^~~~~
stringwrap.h:13:19: note: deduced return type only available with -std=c++14 or -std=gnu++14
stringwrap.h:15:29: error: 'getFirstPosition' function uses 'auto' type specifier without trailing return type
auto getFirstPosition() const;
^~~~~
stringwrap.h:15:29: note: deduced return type only available with -std=c++14 or -std=gnu++14
stringwrap.h:18:55: error: 'determineFirstPosition' function uses 'auto' type specifier without trailing return type
inline auto determineFirstPosition(const std::string s)
^
stringwrap.h:18:55: note: deduced return type only available with -std=c++14 or -std=gnu++14
stringwrap.h: In function 'auto determineFirstPosition(std::__cxx11::string)':
stringwrap.h:35:21: error: inconsistent deduction for auto return type: 'int' and then 'long long unsigned int'
return s.length();
^
stringwrap.cc: At global scope:
stringwrap.cc:7:27: error: 'length' function uses 'auto' type specifier without trailing return type
auto Stringwrap::length() const
^~~~~
stringwrap.cc:7:27: note: deduced return type only available with -std=c++14 or -std=gnu++14
stringwrap.cc:12:37: error: 'getFirstPosition' function uses 'auto' type specifier without trailing return type
auto Stringwrap::getFirstPosition() const
^~~~~
stringwrap.cc:12:37: note: deduced return type only available with -std=c++14 or -std=gnu++14
当我使用auto 并编译--std=c++14 时,出现以下错误:
C:\temp\v0.11>g++ -g -O2 -std=c++14 -Werror=conversion stringwrap.cc
In file included from stringwrap.cc:1:
stringwrap.h: In function 'auto determineFirstPosition(std::__cxx11::string)':
stringwrap.h:35:21: error: inconsistent deduction for auto return type: 'int' and then 'long long unsigned int'
return s.length();
^
问题:如何编写可移植的 C++11 代码(Linux、Windows),避免在 STL 数据类型(如 std::string)中进行类型转换(如上所示)?
【问题讨论】:
-
C++11不支持返回类型推导,需要使用尾随返回类型
auto foo() -> std::string::size_type {...} -
只需使用
size_t。所描述的问题是使用 32 或 64 位构建类型(系统)的结果。 -
@MarekR 这不是便携式的。没有要求
std::string::size_type是size_t。 -
@NathanOliver 在某种意义上是。由于 std::string size_type 是
std::allocator_traits<Allocator>::size_type,而对于标准分配器size_type将是make_unsigned_t<difference_type>,而后者是ptrdiff_t,对于所有意图和目的而言,它都变为size_t。 -
@NathanOliver 没有要求也许可以,但是
size_t应该不小于容器大小类型,因此可以安全使用。
标签: c++ c++11 stl portability stdstring