I have std::tuple filled with objects instantiated from class template with one type parameter. Now I want to get in compile time an element with specified type parameter from my tuple. Here is the code.
template<typename Params, typename Descriptor>
struct IsParamsEqual;
template<typename Params1, typename Params2, ApiCommand::Value value>
struct IsParamsEqual<Params1, Descriptor<value, Params2>>
{
static constexpr bool v = std::is_same<Params1, Params2>::value;
};
template<typename Params, size_t I, typename... Args>
constexpr size_t getIndexByParamsHelper(const IndexSequence<I>&, const std::tuple<Args...> &)
{
return I;
}
template<typename Params, size_t I, size_t... Indexes, typename... Args>
constexpr size_t getIndexByParamsHelper(const IndexSequence<I, Indexes...> &,
const std::tuple<Args...> &tuple)
{
return IsParamsEqual<Params, typename std::tuple_element<I, std::tuple<Args...>>::type>::v ?
I : getIndexByParamsHelper<Params>(IndexSequence<Indexes...>(), tuple);
}
template<typename Params, size_t... Indexes, typename... Args>
constexpr size_t getIndexByParams(const IndexSequence<Indexes...> &seq,
const std::tuple<Args...> &tuple)
{
return getIndexByParamsHelper<Params>(seq, tuple);
}
template<typename Params, typename... Args>
constexpr auto getByParamsImpl(const std::tuple<Args...> &tuple)
{
constexpr size_t I = getIndexByParams<Params>(
typename MakeIndexSequence<sizeof...(Args)>::type(), tuple);
static_assert(std::is_same<typename std::remove_reference<decltype(
std::get<I>(tuple))>::type::paramType, Params>::value,
"Param not found");
return std::get<I>(tuple);
}
This compiles fine on gcc 4.8.4 but not on vs2015u2. The error is in the getByParamsImpl() and it says:
error C2131: expression did not evaluate to a constant
note: failure was caused by non-constant arguments or reference to a non-constant symbol
see usage of 'I'
Obviously, compiler thinks that getIndexByParams() return value is not constexpr. The question is why and more important how this can be fixed?
Aucun commentaire:
Enregistrer un commentaire