可移植性 windows linux,关于Windows与Linux上c ++:std :: string的可移植性和长度

我遇到了一些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::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::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

#include

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 int更改为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),避免在std::string这样的STL数据类型中进行类型转换(如上所示)?

C ++ 11不支持返回类型推断,您需要使用尾随返回类型auto foo() -> std::string::size_type {...}

只需使用size_t。 描述的问题是使用32 o 64位构建类型(系统)的结果。

@MarekR那不是可移植的。 不需要std::string::size_type是size_t。

从某种意义上说是@NathanOliver。 由于std :: string size_type是std::allocator_traits::size_type,对于标准分配器,size_type将是make_unsigned_t,后者是ptrdiff_t,出于所有意图和目的,它将变为size_t。

@NathanOliver也许没有要求,但是size_t应该不小于容器大小类型,因此可以安全使用。

查看std::string文档,您可以看到该类型称为

std::string::size_type

所以就用那个您无需知道或猜测它是typedef的原始类型-您已经有了一个可以保证正确的可用名称。

std::string提供公共类型,例如std::string::size_type,可用于定义函数。您可以像这样定义determineFirstPosition函数

inline std::string::size_type determineFirstPosition(const std::string s)

{

for (std::string::size_type i = 0; i < s.length(); ++i)

{

switch (s.at(i))

{

case ' ':

{

break;

}

default:

{

return i;

}

}

}

return s.length();

}

如果您不想在各处重复std::string::size_type,则可以在类中添加using声明,以缩短名称,例如

using pos_type = std::string::size_type;

然后您只需使用pos_type。

c ++ 11不能使用auto返回类型推导。

对于c ++ 14,请认真阅读以下内容:

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();

}

inline auto determineFirstPosition(const std::string s)

{

for (auto i = 0; i < s.length(); ++i)

{

switch (s.at(i))

{

case ' ':

{

break;

}

default:

{

return i;

}

}

}

return s.length();

}

在这种情况下,您的错误是

for (auto i = 0; i < s.length(); ++i)

因为auto i = 0是int,而不是s.length()的类型。

for (decltype(s.length()) i = 0; i < s.length(); ++i)

如果要避免在此处命名类型。

或者,您可以使用std::string::size_type。另外,您可以编写一个实用程序,使您可以通过for(:)对某些内容进行索引。

template struct tag_t {using type=T;};

template using block_deduction = typename tag_t::type;

template

struct range_t {

It b, e;

It begin() const { return b; }

It end() const { return e; }

};

template

struct indexer_t {

S s;

void operator++(){++s;}

S operator*() const{ return s; }

friend bool operator==( indexer_t const& lhs, indexer_t const& rhs ) {

return lhs.s == rhs.s;

}

friend bool operator!=( indexer_t const& lhs, indexer_t const& rhs ) {

return lhs.s != rhs.s;

}

};

template

range_t indexes( block_deduction start, S finish ) {

return {{std::move(start)}, {std::move(finish)}};

}

template

auto indexes_into( C&& c ) {

return indexes( 0, c.size() );

}

所有这些使您可以:

for( auto i : indexs_into(s) )

代替

for (unsigned long int i = 0; i < s.length(); ++i)

现场示例。

(作为附带奖励,

template

auto iterators_into( C& c ) {

return indexes( c.begin(), c.end() );

}

也是有用的,它允许您将所有有效的迭代器迭代到容器中,而无需手动编写for(;;)循环)

这很有趣。 我不会使用此方法(至少现在不使用),但是我一定会研究这种方法。 这里有些语言功能对我来说是新的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值