gpt4 book ai didi

c++ - constexpr 函数可能存在错误?

转载 作者:行者123 更新时间:2023-12-01 23:32:29 25 4
gpt4 key购买 nike

以下代码是否正确使用了 constexpr 函数?它本质上尝试以各种方式访问​​static constexpr成员变量_size

使用 g++ 编译没有问题,但使用 msvc-2017/2019clang 编译失败。

可通过 godbolt 进行测试的代码示例 here .

<小时/>

如果将 constexpr 函数替换为等效的宏解决方法,则似乎可以(在任何地方)进行编译。取消注释 USE_MACRO_WORKAROUND 进行测试。

对我来说,这似乎表明存在与 constexpr 函数相关的编译器错误?

(由于宏版本有效,这表明编译器应该有足够的编译时信息来处理 constexpr 函数。显然 g++ 可以做到这一点。 ..)

<小时/>

(这个例子只是一个简单的设计。真正的代码是 this library 的一部分)。

#include <cstddef>

//define USE_MACRO_WORKAROUND

template <size_t N = +1>
struct expansion
{
size_t static constexpr _size = N ;
double _xdat [ N ] ;
};

#if defined(USE_MACRO_WORKAROUND)

// ugly macro-based hack that's equiv. to compile
// time foo()...
// does compile everywhere

#define foo(_aa, _bb) _aa._size + _bb._size

#else

// why does this cause problems? works for g++ 7,
// 8, 9, but not msvc, etc

template <size_t NA, size_t NB>
inline size_t constexpr foo (
expansion <NA> const& _aa,
expansion <NB> const& _bb
)
{
return _aa._size + _bb._size;
}

#endif //USE_MACRO_WORKAROUND

template <size_t NA, size_t NB>
inline void goo (
expansion <NA> const& _xx,
expansion <NB> const& _yy
)
{ // this will not compile with msvc, reporting
// C2131: expression did not evaluate to a constant
expansion<foo(_xx, _yy)> _tt;
}

int main ()
{
expansion< 2 > _x2;
expansion< 4 > _x4;

// this seems to work for both g++ and msvc
expansion<foo(_x2, _x4)> _x6;

// via msvc, this leads to the errors above
goo (_x2, _x4) ;

return 0;
}

最佳答案

根据 cppreference.com:

Reference variables can be declared constexpr (their initializers have to be reference constant expressions):

该程序的问题在于您尝试在 constexpr 上下文中使用对运行时变量(在 main 开头声明)的引用。尽管在对象内部访问的变量是全局状态(静态)并且在 constexpr 上下文内部,但在这种情况下不能使用这些运行时变量的地址。除了 GCC 9.0 及更早版本之外,我无法使用任何现代编译器来编译您提供的代码。 GCC trunk 编译失败。

我能够使用我们(系统级程序员)可用的最佳工具之一来测试这一点,Matt Godbolt's Compiler Explorer . Simplified example

有趣的是,如果我们决定在调用 goo() 时按值复制它们,那么这些变量似乎可以使用。通过从函数签名中删除 & 符号,我能够让该程序在每个 clang、gcc 和 msvc 的多个版本上进行编译:

#include <cstddef>
#include <iostream>

template <
size_t N = +1
>
class expansion
{
public:
size_t static constexpr _size = N ;

double _xdat [ N ] ;
size_t _xlen = 0 ;
};

template <
size_t NA, size_t NB
>
inline size_t constexpr foo (
expansion <NA> const& _aa,
expansion <NB> const& _bb
)
{
return _aa._size + _bb._size;
}

template <
size_t NA, size_t NB
>
inline void goo (
expansion <NA> const _xx,
expansion <NB> const _yy
)
{
// this will not compile with msvc, reporting
// C2131: expression did not evaluate to a constant
size_t
constexpr _nn = foo(_xx, _yy);

expansion<_nn> _tt;
}

int main ()
{
expansion< 2 > _x2;
expansion< 4 > _x4;

// this seems to work for both g++ and msvc
size_t
constexpr _n6 = foo(_x2, _x4);

expansion<_n6> _x6;

// via msvc, this leads to the errors above
goo (_x2, _x4) ;

std::cout << _n6 << std::endl;

return 0;
}

编辑:

因为我无法确认这是否是一个编译器错误,(因为我无法重现你所说的结果),我希望我能够帮助你使用你提供的代码,因为我假设这是您遇到过的合法用例。

关于c++ - constexpr 函数可能存在错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60499787/

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