gpt4 book ai didi

c++ - 使用指向方法的指针的 MSVC 编译器 fatal error C1001

转载 作者:行者123 更新时间:2023-12-02 10:29:05 24 4
gpt4 key购买 nike

在编写自定义反射库时,我遇到了一个奇怪的编译器行为。但是,我能够使用非常简化的代码重现该问题。这是:

#include <iostream>

class OtherBase{};

class Base{};

/* Used only as a test class to verify if the reflection API works properly*/
class Derived : Base, OtherBase
{
public:

void Printer()
{
std::cout << "Derived::Printer() has been called" << std::endl;
}
};

/*Descriptor class that basically incapsulate the address of Derived::Printer method*/
struct ClassDescriptor
{
using type = Derived;

struct FuncDescriptor
{
static constexpr const auto member_address{ &type::Printer };
};
};

int main()
{
Derived derived;
auto address{ &Derived::Printer };
(derived.*address)(); // -> OK it compiles fine using the local variable address
(derived.*ClassDescriptor::FuncDescriptor::member_address)(); // -> BROKEN using the address from the descriptor class cause fatal error C1001 !
}
在尝试调试此问题时,我注意到:
  • 仅当 Derived 时才会发生有多重继承。
  • 如果我交换 static constexpr const auto member_address{ &type::Printer }inline static const auto member_address{ &type::Printer }有用。

  • 它只是一个编译器错误,还是我做错了什么?
    我可以在保留 constexpr 的同时解决这个问题吗?
    请注意,我使用的是 MSVC 2017 和编译器版本 19.16.27024.1
    除了启用/std:c++17 之外,所有编译器选项都是默认的。
    我知道将编译器版本更新到最后一个版本(我肯定会这样做)可能会解决这个问题,但现在我想更多地了解这个问题。

    最佳答案

  • 关于 C1001,Microsoft Developer Network 建议您删除代码中的一些优化: fatal error C1001。一旦您确定了导致问​​题的优化,您可以使用 #pragma 仅在该区域禁用该优化:
    //禁用优化
    #pragma 优化(“”,关闭)
    ...
    //重新启用之前的优化
    #pragma 优化(“”,开)

  • 此外, Microsoft 发布了针对此问题的修复程序。 .您可以安装 most recent release .
  • constconstexpr :
  • const将对象声明为常量。这意味着保证一旦初始化,该对象的值就不会改变,并且编译器可以利用这一事实进行优化。它还有助于防止程序员编写修改初始化后不打算修改的对象的代码。 constexpr声明一个对象适合在标准所谓的常量表达式中使用。但请注意 constexpr不是唯一的方法。
    当应用于函数时,基本区别是: const只能用于非静态成员函数,一般不能用于函数。它保证成员函数不会修改任何非静态数据成员。 constexpr可以与成员函数和非成员函数以及构造函数一起使用。它声明了适合在常量表达式中使用的函数。编译器仅在函数满足某些条件(7.1.5/3,4)时才会接受它,最重要的是:
    函数体必须是非虚拟的并且非常简单:除了 typedef 和静态断言,只有一个 return允许声明。在构造函数的情况下,只允许使用初始化列表、typedef 和静态断言。 ( = default= delete 也是允许的。)
    从 C++14 开始,规则更加宽松,从那时起允许在 constexpr 中使用。功能: asm声明,一个 goto语句,标签不是 case 的语句和 default ,try-block,非文字类型变量的定义,静态或线程存储持续时间的变量的定义,不进行初始化的变量的定义。
    参数和返回类型必须是文字类型(即,一般来说,非常简单的类型,通常是标量或聚合)
    我什么时候可以/应该同时使用两者, constconstexpr一起?
    A. 在对象声明中。当两个关键字都引用要声明的同一个对象时,这从来没有必要。 constexpr意味着常量。
    constexpr const int N = 5;
    is the same as

    constexpr int N = 5;
    但是,请注意,在某些情况下,每个关键字都引用声明的不同部分:
    static constexpr int N = 3;

    int main()
    {
    constexpr const int *NP = &N;
    }
    在这里, NP被声明为地址常量表达式,即本身就是常量表达式的指针。 (通过将地址运算符应用于静态/全局常量表达式来生成地址时,这是可能的。)这里, constexprconst需要: constexpr总是指被声明的表达式(这里是 NP ),而 const 指的是 int (它声明了一个指向常量的指针)。删除 const 会使表达式非法(因为 (a) 指向非 const 对象的指针不能是常量表达式,并且 (b) &N 实际上是指向常量的指针)。
    B. 在成员函数声明中。在 C++11 中, constexpr意味着 const,而在 C++14 和 C++17 中则不是这样。在 C++11 下声明为的成员函数
    constexpr void f();
    needs to be declared as

    constexpr void f() const;
    在 C++14 下仍然可以用作 const功能。
    你可以引用这个 link更多细节。

    关于c++ - 使用指向方法的指针的 MSVC 编译器 fatal error C1001,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63076635/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com