当前位置: 首页 > 知识库问答 >
问题:

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

卫学真
2023-03-14

我使用Visual Studio2019来学习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个答案

松旭
2023-03-14

看来是MS VS的一个bug。

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

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

即有使用声明

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

但是,函数begin和end具有不同的返回类型。

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

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

濮阳宁
2023-03-14

我同意@vlad-from-moscow的观点,这可能是一个MSVC bug,因为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 
    } 
}

begin迭代器的类型为FiboIterator,end迭代器的类型为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};
    }
};
 类似资料:
  • 我有一个小函数,它使用从创建一个日期对象,而在ubuntu下使用clang或gcc进行编译,而在windows下不使用msvc。 对于每个调用在编译时显示以下错误: 'std::from_chars':14个重载都不能转换所有参数类型 然后,编译器继续列出可能的重载,我清楚地看到了我试图使用的重载: 'std::from_chars_resultstd::from_chars(const char

  • 下面的代码在g7.2.0中编译成功(编译标志是),但在clang 5.0.0中编译失败(使用相同的标志,)和vc 15.4(编译标志是): 哪种编译器行为符合标准?如何将该模板应用更改为在clang上编译? 叮当声错误消息: VC错误消息:

  • 补充clang++编译后的汇编代码: 编译结果:

  • 问题内容: 以下代码在t3行中出现编译错误: 错误消息是: 类型不匹配:无法从对象转换为T 我知道我可以使用强制转换或手动绑定来解决问题,我的问题是: 编译器进行自动绑定是否如此困难,是否会失败? 编辑:添加了错误消息。 编辑:添加了另一个示例如何不会发生该错误。 编辑:删除了第二个示例,因为它令人困惑,使问题更加清楚。 问题答案: 在第一种情况下,您有两个具有名为的类型参数的泛型方法,但是这些类

  • 我正在开发一个代理适配器,使用Java中的泛型将一个请求/响应转换为另一个请求/响应。 我有一个接口: 适配器的实现(仅以请求案例为例): 抽象类: 从Java中的泛型类型推断泛型类型(编译时错误) 我在那个问题上花了大约三天时间。有什么想法吗?谢了。

  • 所以,我已经通过Chocolate安装了Bazel,安装了Python 3.5和2.7,安装了CUDA v8和cuDNN v6,安装了JDK 8.0,我现在正在尝试在我的Windows 10设备上定制TensorFlow,使用AVX、AVX 2和CUDA。TensorFlow GPU,预构建版本,确实可以工作,我已经测试并成功运行了它。 我遵循了其他文章的说明,包括在TensorFlow的实际站点

  • 我在Eclipse中编写代码,有如下内容: 但是,当我尝试构建时,会出现以下错误: 有什么想法吗?我在谷歌上搜索过,似乎大多数有这个问题的人根本没有包含正确的头文件,我相信我做得是正确的。

  • 问题内容: 是否可以为javac(或某些替代的Java编译器)指定自定义类加载器? 我很喜欢这种壮举,因为它可以让我编译使用仅由我的特殊类加载器找到的类的类。 对于那些好奇的人:我将编写一个连接数据库的classloder,并根据找到的表创建类。 问题答案: 运行javac时,您可以像这样指定类加载器: