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

时间:2020-08-03 12:10:55

标签: c++ visual-c++ compiler-errors 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 ++,应该如何更改代码?谢谢。

2 个答案:

答案 0 :(得分:1)

似乎是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

答案 1 :(得分:1)

我同意@ vlad-from-moscow,这可能是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设为相同,并将FiboIterator的比较运算符也设为相同。

#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};
    }
};
相关问题