可视C++自定义范围类型 MSVC 编译,但 G++ 不编译



我使用Visual Studio 2019来学习C++,因为它是一个很好的IDE,可以当场捕捉错误。我下面的程序没有显示任何错误,并且使用MSVC编译得很好,但当我尝试使用G++10.1编译时,它不会做到

#include <cstdio>
class FiboIterator {
int current{ 1 };
int last{ 1 };
public:
bool operator!=(int x) const {
return x >= current;
}
FiboIterator& operator++() {
const auto tmp = current;
current += last;
last = tmp;
return *this;
}
int operator*() {
return current;
}
};
class FiboRange {
const int max;
public:
explicit FiboRange(int max): max{max} {}
FiboIterator begin() const {
return FiboIterator{};
}
int end() const {
return max;
}
};
int main() {
for (const auto i : FiboRange{ 5000 }) {
printf("%d ", i);
}
}

g++输出以下消息:

main.cpp: In function 'int main()':
main.cpp:34:38: error: inconsistent begin/end types in range-based 'for' statement: 'FiboIterator' and 'int'
34 |  for (const auto i : FiboRange{ 5000 }) {
|                                      ^
main.cpp:34:38: error: conversion from 'int' to non-scalar type 'FiboIterator' requested
main.cpp:34:38: error: no match for 'operator!=' (operand types are 'FiboIterator' and 'FiboIterator')
main.cpp:7:7: note: candidate: 'bool FiboIterator::operator!=(int) const'
7 |  bool operator!=(int x) const {
|       ^~~~~~~~
main.cpp:7:22: note:   no known conversion for argument 1 from 'FiboIterator' to 'int'
7 |  bool operator!=(int x) const {
|                  ~~~~^

MSVC和G++之间有显著差异吗?如果我想让自定义范围与G++一起工作,我应该如何更改我的代码?谢谢

我同意莫斯科的@vlad的观点,这可能是一个MSVC错误,因为Visual Studio 2019的默认设置是C++14。它不应该编译。

您的代码从c++17开始就是正确的。如果您使用c++17,您的代码将在GCC和CLang上编译。

基于范围的for循环的实现方式发生了变化。

C++11:

{
auto && __range = range_expression ; 
for (auto __begin = begin_expr, __end = end_expr; 
__begin != __end; ++__begin) { 
range_declaration = *__begin; 
loop_statement 
}
} 

C++17:

{        
auto && __range = range_expression ; 
auto __begin = begin_expr ;
auto __end = end_expr ;
for ( ; __begin != __end; ++__begin) { 
range_declaration = *__begin; 
loop_statement 
} 
}

起始迭代器的类型为FiboIterator,结束迭代器为int。

// c++11 version fails, auto can't deduce type
auto __begin = begin_expr, __end = end_expr; // an error here
// C++17 version works fine, they are different types.
auto __begin = begin_expr ;
auto __end = end_expr;

如果您不想使用C++17,那么您应该使begin和end的返回类型相同,并使FiboIdeator的比较运算符相同。

#include <cstdio>
class FiboIterator {
int current{ 1 };
int last{ 1 };
public:
FiboIterator(int x=1) : current{x} {}
bool operator!=(FiboIterator x) const {
return x.current >= current;
}
FiboIterator& operator++() {
const auto tmp = current;
current += last;
last = tmp;
return *this;
}
int operator*() {
return current;
}
};
class FiboRange {
const int max;
public:
explicit FiboRange(int max): max{max} {}
FiboIterator begin() const {
return FiboIterator{};
}
FiboIterator end() const {
return FiboIterator{max};
}
};

这似乎是MS VS的一个错误。

特别是基于范围的for循环被转换为类似的语句

for ( auto __begin = begin-expr,
__end = end-expr;
__begin != __end;
++__begin )

那就是使用了申报

auto __begin = begin-expr, __end = end-expr;

但是,函数的开始和结束具有不同的返回类型。

FiboIterator begin() const {
return FiboIterator{};
}
int end() const {
return max;
}

因此,您可能不会在这样的声明中使用占位符说明符auto

相关内容

  • 没有找到相关文章

最新更新