【问题标题】:Someone explain why the ambiguity here, please?有人解释一下为什么这里的模棱两可吗?
【发布时间】:2015-07-02 08:45:07
【问题描述】:

Fill<T, Pack, Size, Value>Pack<Value, Value, ..., Value> 类型,其中 Value 重复 Size 次。谁能解释一下,为什么这是模棱两可的?

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 混淆的问题到底是什么?

【问题讨论】:

  • Fwiw,clang 3.6 咀嚼第一个没有错误。信息:Apple LLVM 版本 6.1.0 (clang-602.0.49)(基于 LLVM 3.6.0svn)。也许包括你的工具链信息。
  • 我在最近的 GCC 4.9.2 中遇到错误。 Visual Studio 2013 也出错。
  • 嗯,clang 显然比我们更聪明,因为它意识到实际上没有使用过。将T t; 添加到main() 提供以下剂量: main.cpp:23:7:未定义模板的隐式实例化 'Pack' .尽管无论如何知道这可能很有用。 编辑纳米。在Pack 之后添加{};,它会再次编译。
  • 我的钱花在了 GCC 的部分专业化排序算法中的一个错误上。我搜索了已知的错误,但找不到任何东西。您可能需要考虑举报。
  • @Brian,也许我在我的问题中更新的第三个示例更清楚地说明 GCC 是否真的被窃听了?第三个示例似乎与第一个具有相同的症状,可以编译。

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


【解决方案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

【讨论】:

  • 不错!我从没想过使用逗号运算符。由于这里只是一个虚拟运算符,我猜任何长度为Size 的 index_sequence 都可以工作。
猜你喜欢
  • 2011-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多