Как объяснил 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...
методу (может быть static
, а также constexpr
, если хотите), используемому для инициализации tmp
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
класс не является "классом вариационных шаблонов".
Это обычный (не шаблонный) класс с одним (двумя, в моем первом решении) конструктором (-ами) вариадических шаблонов.
- EDIT -
ОП спрашивает
Что если мне нужно получить счетчик как статическую переменную 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).
Заметьте, что я определил переменную f8
в main()
как 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 };
, потому что он выводится из номера аргумента конструктора.