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以上是关于Clang 可变参数模板专业化错误:不可演绎的模板参数的主要内容,如果未能解决你的问题,请参考以下文章
为啥接受数组的 C++ 模板并不比接受 GCC 5.3 和 Clang 4.0 的指针更专业?