当前位置: 首页 > 知识库问答 >
问题:

使用lambda编译constexpr时,MSVS2017错误“表达式未计算为常数”

阎咏思
2023-03-14

我使用的是MSVS c 17,下面的代码无法编译:

#include <type_traits>
#include <tuple>

using namespace std;
 
template <size_t Size, class Pred, size_t idx=0, size_t... pass>
constexpr auto makeIndices(const Pred &pred)
{
    if constexpr(idx >= Size)
    {
        return index_sequence<pass...>();
    }
    else if constexpr(pred(integral_constant<size_t, idx>()))  //<-- HERE!!!!
    {
        return makeIndices<Size, Pred, idx+1, pass..., idx>(pred);
    }
    else
    {
        return makeIndices<Size, Pred, idx+1, pass...>(pred);
    }
}

template <class Tuple, size_t... I>
constexpr auto extract(Tuple&&v, index_sequence<I...> = index_sequence<I...>())
{
    return tuple<tuple_element_t<I, decay_t<Tuple>>...>(get<I>(forward<Tuple>(v))...);
}

template <class Tuple, class Pred>
constexpr auto extract(Tuple&&v, const Pred &pred)
{
    return extract(std::forward<Tuple>(v), makeIndices<tuple_size_v<decay_t<Tuple>>>(pred));
}

template <class Target, class Tuple>
constexpr auto del(Tuple &&v)
{
    return extract(std::forward<Tuple>(v), [](auto idx)
    {
        return !is_same_v<Target, tuple_element_t<idx(), decay_t<Tuple>>>;
    });
}

void MyFunc()
{
    auto src = make_tuple("one", 1, "two", 2, "three", 3, "fourty", 40);
    del<int>(src);
}

在函数“makeIndices”中,我标记了出现错误的地方。它看起来像:

错误C2131:表达式未计算为常量

注意:失败是由于在变量的生命周期之外读取了变量导致的

注:参见“pred”的用法

注意:请参阅对函数模板实例化“auto makeIndices”的引用

上面的代码在GCC(Link)中编译并正常工作。

但是如何为MSVS修复它呢?

共有1个答案

霍建柏
2023-03-14

根据评论,MSVC拒绝这一点是正确的。< code>pred是一个引用,在函数体内部,不知道< code>pred引用的是什么对象。因此,< code>pred(...)不允许出现在常量表达式中,即使它实际上根本不会使用< code>pred。

不过,您可以做的是通过值传递pred(更改constPred

 类似资料:
  • 问题内容: 我有以下代码: 当我通过main方法运行它时,它运行良好,但是当我尝试对其进行编译时,抛出以下错误: 我正在使用Eclipse IDE,并尝试通过命令行进行编译。 问题答案: 默认情况下,使用Java 5来编译类。引用其文档: 还要注意,当前的默认源设置是1.5,默认目标设置是1.5,与运行Maven的JDK无关。如果要更改这些默认值,则应按照设置Java编译器的- source和-t

  • 我正在使用NetBeans 8。当我的代码包含Lambda表达式并尝试编译时,我会收到以下错误消息:

  • 由于声明为constexpr的函数有可能在运行时调用,编译器根据哪些条件决定是在编译时还是在运行时计算它? 在这种情况下,i在编译时是未知的,这可能是编译器将POW()视为在运行时调用的常规函数的原因。然而,这种动态,尽管看起来很方便,却有一些不切实际的含义。例如,会不会有这样一种情况,我希望编译器在编译时计算一个常数表达式函数,而编译器决定将其视为正常函数,而它在编译时也可以工作?有什么已知的常

  • 问题内容: 我正在使用NetBeans8。当我的代码包含Lambda表达式并尝试编译时,出现以下错误消息: 问题答案: 将源代码的编译器版本更改为jdk 8的项目属性,然后首先检查是否已安装。

  • 我有这个非常简单的打字稿文件: 然后我运行: 打字稿编译器(版本1.8.7,OS X)抱怨: 我如何修复这个错误?谢谢你。

  • 常量表达式机制是为了: 提供一种更加通用的常量表达式 允许用户自定义的类型成为常量表达式 提供了一种保证在编译期完成初始化的方法(可以在编译时期执行某些函数调用) 考虑下面这段代码: enum Flags { good=0, fail=1, bad=2, eof=4 }; constexpr int operator|(Flags f1, Flags f2) { return Flags(int(