为什么会导致模糊的模板错误?

时间:2017-12-03 16:01:52

标签: c++ c++11 templates c++14

我不明白为什么会这样:

template <typename...U>
struct 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;

导致模糊的部分专业化:

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...>
       ^

从我的POV,当第一个参数是0时,它必须接受第一个参数作为匹配。

请注意,我并没有找到解决这个问题的方法,我不知道为什么这不起作用。什么部分专业化规则禁止这个? 这发生在 clang g++ 中,我认为 vc++ 因同样的原因不匹配,即使错误没有帮助。

1 个答案:

答案 0 :(得分:4)

这是因为部分订购。你的两个部分特化在另一个方面比另一个更好,所以调用是不明确的,因为如果它们同样好的话,编译器不能说两者中的哪一个是更好的匹配。

第一个专业化比第二个专业化要好,因为正如你所说,使用了0。精确匹配优于第二次专业化的一般情况。

第二个特化比第一个更好,因为它采用单个类型参数,而不是可变参数。基本上,对于部分排序,T, Ts...优于Ts...