有人解释了为什么这里有歧义吗?

时间:2015-04-23 22:52:03

标签: c++ templates c++11 variadic-templates

Fill<T, Pack, Size, Value>将是Pack<Value, Value, ..., Value>类型,其中值重复大小时间。有人可以解释,为什么这是不明确的?

template <typename T, template <T...> class Pack, int Size, int Count, typename Output, T Value>
struct FillHelper;

template <typename T, template <T...> class P, int Size, int Count, T... Output, T Value>
struct FillHelper<T, P, Size, Count, P<Output...>, Value> :
    FillHelper<T, P, Size, Count + 1, P<Output..., Value>, Value> {};

template <typename T, template <T...> class P, int Size, T... Output, T Value>
struct FillHelper<T, P, Size, Size, P<Output...>, Value> {
    using type = P<Output...>;
};

template <typename T, template <T...> class P, int Size, T Value>
using Fill = typename FillHelper<T, P, Size, 0, P<>, Value>::type;

template <int...> struct Pack;

int main() {
    using T = Fill<int, Pack, 10, 4>;
}

虽然不是这样:

template <typename T, int Size, int Count, typename Output, T Value>
struct FillHelper;

template <typename T, template <T...> class P, int Size, int Count, T... Output, T Value>
struct FillHelper<T, Size, Count, P<Output...>, Value> :
    FillHelper<T, Size, Count + 1, P<Output..., Value>, Value> {};

template <typename T, template <T...> class P, int Size, T... Output, T Value>
struct FillHelper<T, Size, Size, P<Output...>, Value> {
    using type = P<Output...>;
};

template <typename T, template <T...> class P, int Size, T Value>
using Fill = typename FillHelper<T, Size, 0, P<>, Value>::type;

template <int...> struct Pack;

int main() {
    using T = Fill<int, Pack, 10, 4>;
}

事实证明,我间接注意到第二个更短,因此比第一个更好,但我很困惑为什么第一个不能编译。 我收到GCC 4.9.2的错误,这是最近的。 Visual Studio 2013也出错。 顺便说一下,比第二个代码更好的解决方案受到欢迎。

更新:进一步减少问题,事实证明专业化中模板模板的存在不是问题,因为这可以用GCC 4.9.2(和Visual Studio 2013)编译太):

template <typename T, template <T...> class Pack, int Size, int Count>
struct F;

template <typename T, template <T...> class P, int Size, int Count>
struct F : F<T, P, Size, Count + 1> {};

template <typename T, template <T...> class P, int Size>
struct F<T, P, Size, Size> {
    using type = int;
};

template <int...> struct Pack;

int main() {
    using T = F<int, Pack, 10, 0>::type;
}

那么第一个代码中究竟出现了导致与GCC和VS混淆的问题究竟是什么?

1 个答案:

答案 0 :(得分:1)

我不知道为什么GCC拒绝你的代码,但如果你有C ++ 14的支持,一个不太繁琐的解决方案是使用std::make_index_sequence构建具有Size元素组,然后推断包装并再次展开,如下:

template <typename T, template <T...> class Pack, T Value, size_t... indices>
auto FillHelper(std::index_sequence<indices...>) -> Pack<(indices, Value)...>;

template <typename T, template <T...> class P, int Size, T Value>
using Fill = decltype(FillHelper<T, P, Value>(std::make_index_sequence<Size>()));

链接:http://coliru.stacked-crooked.com/a/7771560a1f32461d