C++ 条件constexpr函数

C++ 条件constexpr函数,c++,c++11,constexpr,C++,C++11,Constexpr,这里有一个例子,函数可能是constexpr。通常,添加constexpr并仅在上下文允许的情况下使用常量求值。但是,尽管未在constexpr上下文中使用,但仍存在以下代码投诉: template <typename T> struct Wrapper { friend constexpr bool operator==(const Wrapper& crLhs, const Wrapper& crRhs) noexcept { re

这里有一个例子,函数可能是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 = {};
};
模板
结构包装器
{
friend constexpr bool运算符==(const Wrapper&crLhs、const Wrapper&crRhs)无异常
{
返回crLhs.m_t==crRhs.m_t;
}
T m_T={};
};
使用Visual Studio 2017 15.9.20,这会给出“错误C3615:constexpr函数”运算符==“无法生成常量表达式”,例如,当为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
}
void f()
{
布尔b;
包装a;
b=a==a;//好的
包装纸c;
b=c==c;//C3615,但不使用constexpr上下文
}
我可以通过使用成员模板或删除constexpr来应用解决方法,但这里有什么花招可以做到两全其美(即,在适用时使用constexpr)?

您的代码很好。这是旧版本MSVC中的一个bug。 这个错误在MSVC版本19.22中修复,编译时没有错误。在这里,我们可以看到两个编译器版本的并排:

19.22之后(包括19.22)的所有版本都会编译它,但19.21及以下版本会错误地给出错误C3615,即使这两个版本都设置为使用C++11

GCC和Clang从来没有这个bug。 这个bug只出现在MSVC中,即使是非常旧的GCC和Clang版本也会编译代码而不会给您一个错误

你该怎么办?
如果可能的话,您应该只移动到较新版本的VisualStudio。这是升级编译器的最简单选项,如果您移动到较新版本,编译器应该会收到错误修复和升级。如果这不是一个选项,我会用谷歌搜索不同的方法来升级编译器本身。这个

constexpr
并不意味着它是在编译时计算的(正如您已经知道的),但它确实意味着它必须能够在编译时计算time@idclev:我知道,并且可能在编译时对某些类型进行评估。因此,constexpr。仅对其他类型不适用。constepxr很酷,您也可以在none-constexpr上下文中调用它。但如果在上述情况下出现此错误,则不会。如果您知道它,那么不在constexpr上下文中使用/实例化它又有什么关系呢?无论如何,这并没有改变实际的问题。@idclev:这是一个简化的案例。它是一种包装纸;有时用于内置类型;有时用于更复杂的类型。对于内置类型,我们使用相等运算符的constexpr求值。FYI
/std:c++11
不起作用(编译器抱怨)。它从参数
/std:c++14
开始工作。我应该如何告诉它在编译时使用c++11?VS在添加c++11支持后引入此开关。在早期版本中,你总是能得到最新的C++ VS。由于许多库依赖关系,转移到新的Visual Studio不是那么容易。这些依赖于旧的编译器版本吗?