- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
以下代码是否正确使用了 constexpr
函数?它本质上尝试以各种方式访问static constexpr
成员变量_size
。
使用 g++
编译没有问题,但使用 msvc-2017/2019
和 clang
编译失败。
可通过 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;
}
最佳答案
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/
在 ubuntu gcc 8.0 中: void bar(){} constexpr int foo(int a) { if (a <=0 ) bar(); retur
考虑一个在运行时只包装一个值的类: template class NonConstValue { public: NonConstValue(const Type& val)
在试验 constexpr 函数和模板(以及非类型模板参数)时,我偶然发现了一个现象,我无法理解是哪条规则使它生效。 所以根据 constexpr-s 的规则,我的问题本质上是“为什么会发生这种情况”
我正在阅读 Nicolai M. Josuttis 所著的“C++ 17 The Complete Guide”一书,无法理解以下示例 auto squared1 = [](auto val) con
(使用 g++ 7.0 主干。) 给定以下“类型到值包装”实用程序... template struct type_wrapper { using type = T; }; // "Wraps" a
我编写了一些代码,它能够根据调用站点提供与给定函数关联的字符串(通过函数指针和并行数组的tuple)来分派(dispatch)给函数。 dispatch 函数不直接接受字符串,而是接受 Callabl
如果我想使用一些方便的东西,比如 make_array 我没有机会先声明我的数组,然后再像“早些时候”那样进行定义,因为我的 var 类型不可用定义前。 所以我找到了这个答案: Undefined r
使用 gcc (HEAD 7.0.0 201612) 我惊讶地发现这有效: constexpr long value(const char *definition) { if (definit
我有这个片段。 #include #include struct JustStr { JustStr(const std::string& x) : val(x) {} stati
我找不到任何关于新 C++17 if 初始化语法的信息和“constexpr if”在: http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p01
考虑以下函数: template auto concatenate(std::array &data1, std::array &data2) { std::array result;
假设我有以下对象: #include class Foo { public: constexpr Foo() {}; constexpr std::string foo() cons
我正在尝试使用 https://github.com/gdelugre/literal_ipaddr它说它是一个 C++17 constexpr implementation of inet_addr
我想重新定义unique_ptr用一个特殊的析构函数。因此,我使用以下代码尝试模仿 unique_ptr 的一些构造函数.遗憾constexpr施 worker 员拒绝 build ,我不知道为什么。
我想用结构名称的哈希值初始化一个结构成员。 constexpr uint32_t myHash(const char* const data) { //Some code for hash r
我正在尝试编译 C++ 库(使用 gcc 5.3.1-14ubuntu2)并遇到此类错误: > In file included from > /root/pitchfork/workspace/un
设置: 我有一个使用 SIMD 内部函数的函数,我想在一些 constexpr 函数中使用它。 为此,我需要将其设为 constexpr。但是,SIMD 内在函数没有标记为 constexpr,编译器
这是一个简化的代码示例,旨在生成任意值序列(在 std::iota 的意义上)和在它们之上的不同类别的迭代器: struct delta { template void inc(I&
考虑以下函数: template auto concatenate(std::array &data1, std::array &data2) { std::array result;
我偶然发现了调用非 constexpr 函数的 constexpr 模板函数:在以下代码段中,由于调用了非 constexpr set,bar 无法按预期编译,但 foo 可以编译。谁能告诉我 foo
我是一名优秀的程序员,十分优秀!