Ошибка MSVS2017 «выражение не оценивается как константа» при компиляции constexpr с лямбда-выражением - PullRequest
0 голосов
/ 10 июня 2018

Я использую 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 <8, Pred, 0,> (const Pred &)', скомпилированный ...

Приведенный выше код скомпилирован и прекрасно работает с GCC ( Link ).

Но как это можно исправить для MSVS?

1 Ответ

0 голосов
/ 11 июня 2018

Согласно комментариям, MSVC вправе отклонить это.pred является ссылкой, а внутри тела функции неизвестно, к какому объекту pred относится.Следовательно, pred(...) недопустимо в константных выражениях, даже если оно вообще не будет использовать pred.

Что вы можете сделать, это передать pred по значению (изменить const Pred &predдо Pred pred).Тогда pred обязательно будет ссылаться на действительный объект, и этого достаточно, чтобы MSVC принял вызов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...