Reputation: 2571
I am using MSVS c++17 and the code below can`t be compiled:
#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);
}
In the function "makeIndices" I marked place where error appears. Its looks like:
error C2131: expression did not evaluate to a constant
note: failure was caused by a read of a variable outside its lifetime
note: see usage of 'pred'
note: see reference to function template instantiation 'auto makeIndices<8,Pred,0,>(const Pred &)' being compiled ...
The code above compiled and worked fine with GCC (Link).
But how it could be fixed for MSVS?
Upvotes: 0
Views: 4669
Reputation:
Per the comments, MSVC is right to reject this. pred
is a reference, and inside the function body, it is unknown what object pred
refers to. Therefore, pred(...)
is not allowed in constant expressions, even if it wouldn't actually use pred
at all.
What you can do though, is pass pred
by value (change const Pred &pred
to Pred pred
). Then, pred
will assuredly refer to a valid object, and that is enough to get MSVC to accept the call.
Upvotes: 1