正如 VTT 所解释的,在构造函数体内调用 Counter() 会创建一个新的 Counter() 对象。
您可以递归调用构造函数,但您必须在初始化列表中执行此操作:查找“委托构造函数”以获取更多信息。
我还建议您不要在构造函数体内初始化(和修改)成员对象。
如果您的目标是用参数的数量初始化count,用最后一个参数的值初始化tmp,我提出以下(基于“标签调度”)的解决方案
class Counter
{
private:
struct tag
{ };
int count = 0;
int tmp;
Counter (tag tg, std::size_t c0, int t) : count(c0), tmp{t}
{ std::cout << "end: " << tmp << ", " <<count << "\n"; }
template <typename... Rest>
Counter (tag t0, std::size_t c0, int t, Rest... rest)
: Counter{t0, c0, rest...}
{ std::cout << "recursion: " << tmp << ", " << count << "\n"; }
public:
template <typename... Rest>
Counter (Rest... rest) : Counter{tag{}, sizeof...(Rest), rest...}
{ std::cout << "start: " << tmp << ", " << count << "\n"; }
};
您还可以避免标签分派和构造函数递归,将关于 rest... 的递归委托给用于初始化 tmp 的方法(可能是 static 和 constexpr)
class Counter
{
private:
int count = 0;
int tmp;
static int getLastInt (int i)
{ return i; }
template <typename ... Rest>
static int getLastInt (int, Rest ... rs)
{ return getLastInt(rs...); }
public:
template <typename... Rest>
Counter (Rest... rest)
: count(sizeof...(Rest)), tmp{getLastInt(rest...)}
{ std::cout << tmp << ", " << count << "\n"; }
};
题外话:确切地说,您的Counter 类不是“可变参数模板类”。
这是一个普通的(不是模板)类,有一个(在我的第一个解决方案中是两个)可变参数模板构造函数。
-- 编辑--
OP 询问
如果我需要在编译时间内获取计数作为静态 const 变量和具有计数器长度的 int 数组并作为类成员怎么办? (数组将填充所有构造函数参数)这在 C++ 的可能性范围内吗?
只有当计数器是类的所有实例之间的公共值时,静态常量(也可能是 constexpr)才有意义。
目前没有意义,因为您的 Counter 接受不同长度的初始化列表。
但是假设构造函数的参数编号是一个模板参数(比如N)......在这种情况下,count 只是N 并且可以是static constexpr。您可以为这些值定义一个std::array<int, N>(也是一个int[N],但我建议尽可能避免使用C 样式的数组,而是使用std::array),并且,使构造函数constexpr,你可以强加编译时初始化。
以下是一个完整的 C++14 编译示例(使用 std::make_index_sequence 和 std::index_sequence,不幸的是,它们只能从 C++14 开始使用)。
请注意,我已将main() 中的f8 变量定义为constexpr:只有这样您才能强加(假设没有原样规则)f8 在编译时被初始化
#include <array>
#include <iostream>
#include <type_traits>
template <typename T, std::size_t>
using getType = T;
template <std::size_t N, typename = std::make_index_sequence<N>>
struct foo;
template <std::size_t N, std::size_t ... Is>
struct foo<N, std::index_sequence<Is...>>
{
static_assert( sizeof...(Is), "!" );
static constexpr auto count = N;
const std::array<int, N> arr;
constexpr foo (getType<int, Is> ... is) : arr {{ is ... }}
{ }
};
int main ()
{
constexpr foo<8u> f8 { 2, 3, 5, 7, 11, 13, 17, 19 };
for ( auto const & i : f8.arr )
std::cout << i << ' ';
std::cout << std::endl;
}
如果你可以使用支持C++17的编译器,你也可以使用foo的推导指南
template <typename ... Args>
foo(Args...) -> foo<sizeof...(Args)>;
所以不需要解释定义f8的模板参数
// .......VVV no more "<8u>"
constexpr foo f3{ 2, 3, 5, 7, 11, 13, 17, 19 };
因为它是从构造函数的参数个数推导出来的。