dimanche 3 décembre 2017

Why would this cause an ambiguous template error?

I don't understand why the following:

template <typename...U>
using always_false = std::false_type;

template <size_t I, typename FRONT, typename...Ts>
struct split_impl
{
    static_assert(always_false<Ts...>::value, "Not enough types to index");
};

template <typename...Ts, typename...Us>
struct split_impl<0, std::tuple<Ts...>, Us...>
{
    using front = std::tuple<Ts...>;
    using rest = std::tuple<Us...>;
};

template <size_t I, typename...Ts, typename T, typename...Us>
struct split_impl<I, std::tuple<Ts...>, T, Us...>
    : split_impl<I - 1, std::tuple<Ts..., T>, Us...>
{};

template <size_t I, typename...Ts>
struct split : split_impl<I, std::tuple<>, Ts...> {};

template<int> struct x {};

split<0, x<0>, x<1>>::rest z = nullptr;

results in an ambiguous partial specialization:

source_file.cpp:15:8: note: partial specialization matches [with Ts = <>, Us = <x<0>, x<1>>]
struct split_impl<0, std::tuple<Ts...>, Us...>
       ^
source_file.cpp:22:8: note: partial specialization matches [with I = 0, Ts = <>, T = x<0>, Us = <x<1>>]
struct split_impl<I, std::tuple<Ts...>, T, Us...>
       ^

From my POV, when the first parameter is 0, it must accept the first as being a match.

Please note that I'm not looking for a way to get around this, I'm asking why this is not working. What partial specialization rules are forbidding this? This happens in clang, g++ and I assume vc++ is not matching for the same reason, even though the error is not helpful.

Aucun commentaire:

Enregistrer un commentaire