首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >可能的错误与警察的功能?

可能的错误与警察的功能?
EN

Stack Overflow用户
提问于 2020-03-03 03:46:36
回答 1查看 130关注 0票数 3

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

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

代码样例可通过戈德波特这里进行测试。

如果将constexpr函数替换为等效的宏解决方案,则这似乎可以用于编译(无处不在)。删除要测试的USE_MACRO_WORKAROUND

对我来说,这似乎是一个与constexpr函数相关的编译器错误?

(因为宏版本起作用,这意味着编译器应该有足够的编译时信息来处理constexpr函数。显然,g++可以做到这一点.)

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

代码语言:javascript
复制
#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;
}
EN

回答 1

Stack Overflow用户

发布于 2020-03-03 07:25:21

根据cppreference.com的说法:

可以声明引用变量(它们的初始值必须是引用常量表达式):

这个程序的问题是,您试图使用对运行时变量的引用(在main开头声明)。虽然在对象内部访问的变量是全局状态(静态的),并且是在constexpr上下文中,但是在这种情况下不能使用这些运行时变量的地址。除了GCC、9.0和之前的版本,我无法获得您提供的任何现代编译器编译的代码。GCC树干编译失败。

马特·戈德波特的编译器探索者. i能够使用我们可以使用的最好的工具之一,系统级程序员 简化示例来测试这一点。

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

代码语言:javascript
复制
#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;
}

编辑:

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/60499787

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档