【问题标题】:conditional constexpr functions条件 constexpr 函数
【发布时间】:2020-06-09 11:05:15
【问题描述】:

我在这里有一个函数可能是 constexpr 的情况。通常,只有在上下文允许的情况下才会添加 constexpr 并使用常量评估。然而,尽管没有在 constexpr 上下文中使用它,但以下代码抱怨:

template <typename T>
struct Wrapper
{
    friend constexpr bool operator==(const Wrapper& crLhs, const Wrapper& crRhs) noexcept
    {
        return crLhs.m_t == crRhs.m_t;
    }

    T m_t = {};
};

使用 Visual Studio 2017 15.9.20 这会给出“错误 C3615: constexpr function 'operator ==' cannot result in a constant expression”,例如为 std::string 实例化。信息是正确的,但我没有在 constexpr 上下文中实例化它。

void f()
{
   bool b;

   Wrapper<int>  a;

   b = a == a; //ok

   Wrapper<std::string> c;

   b = c == c;  //C3615, but not using constexpr context
}

我可以通过使用成员模板或删除 constexpr 来应用解决方法,但这里有什么奇特的技巧可以两全其美(即适用时的 constexpr)?

【问题讨论】:

  • constexpr 并不意味着它是在编译时评估的(正如您已经知道的那样),但它确实意味着它必须可以在编译时评估它
  • @idclev:我知道,它可能会在编译时针对某些类型进行评估。因此 constexpr。只是不适用于其他类型。 constepxr 很酷,您也可以在非 constexpr 上下文中调用它。但如果在上述情况下弹出此错误,则不会。
  • 如果你知道它,那么为什么在 constexpr 上下文中使用/实例化它很重要?无论如何,它不会改变实际的问题。
  • @idclev:这是一个简化的案例。它是一种包装器;有时用于内置类型;有时用于更复杂的类型。对于内置类型,我们使用相等运算符的 constexpr 评估。

标签: c++ c++11 constexpr


【解决方案1】:

你的代码没问题。这是旧版 MSVC 中的错误。

此错误已在 MSVC 版本 19.22 中修复,并且编译没有错误。在这里我们可以看到两个编译器版本的并排:https://godbolt.org/z/79kXFm

19.22 及之后的所有版本都会编译它,但 19.21 及更低的版本会错误地给您错误 C3615,即使它们都设置为使用 C++11。

GCC 和 Clang 从来没有这个错误。

该错误仅存在于 MSVC 中,即使是非常旧版本的 GCC 和 Clang 也可以编译代码而不会出现错误。

你应该怎么做?

如果可能,您应该迁移到较新版本的 Visual Studio。这是升级编译器最简单的选项,如果您迁移到更新版本,编译器应该会收到错误修复和升级。如果这不是一个选项,我会用谷歌搜索不同的方法来升级编译器本身。这个might be helpful

【讨论】:

  • 仅供参考 /std:c++11 不起作用(编译器抱怨)。它从参数/std:c++14开始工作。
  • 编译时如何告诉它使用C++11?
  • VS 在添加 C++11 支持后引入此开关。在早期版本中,您总是可以获得 VS 可以提供的最新 C++。
  • 好的,谢谢。由于有许多库依赖项,迁移到新的 Visual Studio 并不容易。
  • 这些是否依赖于旧的编译器版本?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-22
  • 2021-05-29
相关资源
最近更新 更多