Clang 可变参数模板专业化错误:不可演绎的模板参数

Posted

技术标签:

【中文标题】Clang 可变参数模板专业化错误:不可演绎的模板参数【英文标题】:Clang variadic template specialization error: non-deducible template parameter 【发布时间】:2014-09-28 03:37:35 【问题描述】:

我用 clang++-600.0.51 编译以下代码:

template<typename ... Args> struct seq;
template<typename Seq, size_t c = 1> struct pop_back;

template<typename ... Args> struct pop_back <seq<Args...>,  0>
    typedef seq<Args...> type;
;
template<typename ... Args, typename T, size_t c> struct pop_back <seq<Args..., T>,  c>
    typedef typename pop_back<seq<Args...>, c - 1>::type type;
;

我得到一个错误:类模板部分特化包含模板参数 无法推断;这个部分特化永远不会被使用 [-Werror]

好像我对可变参数模板的特化方式不对,但是gcc 4.8.2和vc 2013可以编译成功。如果我只是像上面那样定义pop_back,gcc和vc都通过了.如果我实例化pop_back,它们都会失败。

我的代码不标准吗?如何为此编写解决方法?

【问题讨论】:

很难说,因为我们不知道seq 是什么。 我错过了 seq 定义。添加它。 【参考方案1】:

T 无法推断,因为编译器无法确定参数包Args... 的结尾。你需要一个不同的实现。这一个连接序列的各个元素,而 c 减少。

namespace detail

template <typename S1, typename S2>
struct concat_impl;

template <typename... Ts, typename... Us>
struct concat_impl<seq<Ts...>, seq<Us...>>

    using type = seq<Ts..., Us...>;
;

template <typename S1, typename S2>
using concat = typename concat_impl<S1, S2>::type;

template <typename Seq, size_t c = 1, typename = void>
struct pop_back;

template <typename T, typename... Args, size_t c>
struct pop_back<seq<T, Args...>,  c, typename std::enable_if<c!=0>::type>

    using type = concat<seq<T>, typename pop_back<seq<Args...>, c-1>::type>;
;

template <typename... Args>
struct pop_back<seq<Args...>, 0>

    using type = seq<>;
;
 // detail

template <typename Sequence, size_t c>
struct pop_back;

template <typename... Args, size_t c>
struct pop_back<seq<Args...>, c> : detail::pop_back<seq<Args...>, sizeof...(Args) - c>
 ;

Live Demo

【讨论】:

如果有人能推荐一个不使用enable_if的版本,将不胜感激。 我必须将这个问题保存在某个地方,并将其作为允许推断 Args..., T 的正当理由(因为严重的是,不允许这样做的唯一原因是“因为它没有 [lots of?] 用例,只会增加复杂性”)。 你是对的。我误解了 C++ 标准。如果我的理解是正确的,那么您的 concat 不会按预期工作,例如,如果 c 为 1 且 Seq 为 Seq。无论如何,我明白了你的解决方案的重点,我可以完成这个问题的其余部分。非常感谢! @Griwes,我完全同意你的看法。我认为我的想法是自然,这在技术上是可能的,对吧? ^_^ @wingfire 抱歉,我之前的编辑工作不正常。它已经更新为可以使用的版本。

以上是关于Clang 可变参数模板专业化错误:不可演绎的模板参数的主要内容,如果未能解决你的问题,请参考以下文章

为啥可变参数模板的模板特化与非可变模板的特化不同?

解决 VC++12 中的模板专业化错误?

C++11 中的非类型可变参数函数模板

为啥接受数组的 C++ 模板并不比接受 GCC 5.3 和 Clang 4.0 的指针更专业?

中继可变参数模板参数时出现 Visual Studio 错误 [重复]

如何让clang忽略c-c++不兼容错误?