我之前曾问过类似的问题,了解我可以通过部分特化使它起作用。但是,为了了解可变参数模板的基础知识,我修改了这样的代码。
template<typename T, typename... args>
struct counter{
static const int value= 1+ counter<args...>::value;
};
template<typename T>
struct counter<T>{
static const int value = 0;
};
错误:“对不起,未实现:无法将'args ...'扩展为固定长度的参数列表”
我了解这是错误,已在gcc 4.7.0中修复
因此要解决所有这些问题,我们必须使用把戏或任何东西,这是部分专门化模板的方法。
template<typename... Args> struct counter;
template<>
struct counter<> {
static const int value = 0;
};
template<typename T, typename... Args>
struct counter<T, Args...> {
static const int value = 1 + counter<Args...>::value;
};
实际问题:我真的想知道部分特化在这里有什么特殊作用,以便代码起作用,或者我应该问部分特化如何解决问题? (为什么第二个版本没有找到bug?)。关于动机问题和示例的任何解释将非常有帮助。
最佳答案
第二个版本避免了该错误,因为主模板被声明为template<typename...>
,即它是可变的。该错误的关键是在错误消息中:“对不起,未实现:无法将'args ...'扩展为定长参数列表”(强调我的意思)。
因此,counter<Args...>::value
将在第二种情况下起作用,因为counter
被定制为接受任意数量的参数。但是,在将主模板声明为template<typename T, typename... args>
的第一种情况下,编译器必须将args
分为定长部分(T
)和可变参数部分(新的args
)。大概这就是您的GCC版本中未实现的功能。
我没有理由相信,任何允许第二种情况的<T, Args...>
特化与<typename...>
主模板匹配的机制都可以用于固定长度扩展。
(最后,由于GCC将对C++ 11功能的支持标记为“实验性”,因此您实际上对什么将起作用,什么将不起作用没有任何期望,更不用说为什么和如何了。这些问题只能由GCC开发人员在他们的邮件列表中合理地回答,而不是我们。我们不在乎读者。)