我想知道为什么这个程序没有按预期工作。
#include <iostream>
#include <utility>
#include <list>
template <typename... Args>
struct prank
: std::integral_constant<std::size_t, 9> {};
template <template <typename...> class C,typename T, typename ...Args>
struct prank<C<T,Args...>>
: std::integral_constant<
std::size_t,
1+ prank<Args...>::value> {};
int main()
{
using T = std::list<int>;
std::cout << prank<T>::value << "\n";
}
输出为11但应为10。
让我解释原因:
在main()
我们使用prank<T>
致电std::list<int>
。
它有两个选择,按分辨率规则,它选择模板的第二个特化。
然后在:
template <template <typename...> class C,typename T, typename ...Args>
struct prank<C<T,Args...>>
C
变为std::list
,T
变为int
,Args
变为empty
然后我们从
继承它std::integral_constant<
std::size_t,
1+ prank<Args...>::value>
std::integral_constant
的第二个变量变为1 + prank<Args...>
,prank<Args...>
本身将使用空Arguments包调用第一个恶作剧的结构,并且在继承该结构的std::integral_constant
值成员后变为9 。
所以1+ prank<Args...>::value
应该变成1 + 9 = 10而不是11 !!
但似乎prank<Args...>
同时制作和使用2个结构! (struct prank<C<T,Args...>>
和struct prank
)
这是一个错误还是我犯了错误? (我正在使用gcc 4.8.1)
答案 0 :(得分:3)
问题是你假设std::list
只有一个模板参数,导致prank<std::list<int>>
的实例化,这将导致prank<int>
的实例化
但这是不正确的,因为std::list
在int
后面有一个default-template参数,即分配器:std::allocator<int>
。
template<class T, class Allocator = std::allocator<T>>
class std::list;
std::list<int> => std::list<int, std::allocator<int>>
template <typename... Args>
/* (A) -> */ struct prank : std::integral_constant<std::size_t, 9> {};
template <template <typename...> class C,typename T, typename ...Args>
/* (B) -> */ struct prank<C<T,Args...>>
: std::integral_constant<std::size_t, 1+ prank<Args...>::value> {};
实例化,按顺序:
prank<std::list<int, std::allocator<int>>>
prank<std::allocator<int>>
prank<int>
总收益率?的 11 强>