2016-06-08 12 views
0

У меня есть следующий фрагмент кода:Любопытно повторяющееся шаблон шаблон с переменным числом шаблонов (C++)

#include <iostream> 

template <typename Derived> 
struct Base { 
    void print() const { static_cast<const Derived*>(this)->print(); } 
}; 

struct Value : public Base<Value> { 
    int i; 
    void print() const { std::cout << "Value: " << i << std::endl; } 
    Value(int j) : i(j) {} 
}; 

void do_variadic_thing() {} 

template <typename Derived, typename... Args> 
void do_variadic_thing(const Base<Derived>& b, Args... args) { 
    std::cout << "Inside do_variadic_thing" << std::endl; 
    b.print(); 
    do_variadic_thing(args...); 
} 

template <typename Derived> 
void do_thing(const Base<Derived>& b) { 
    std::cout << "Inside do_thing" << std::endl; 
    b.print(); 
    do_variadic_thing(b, b, b); 
} 

int main(int argc, char** argv) { 
    do_thing(Value(1)); 
} 

Этот код использует Любопытно Периодическая шаблона шаблон определить время компиляции полиморфный класс с методом под названием print.

Что я хочу сделать, это запустить метод print из функции с переменным числом аргументов (do_variadic_thing). Код Приведенный выше компилируется, но производит странный вывод:

Inside do_thing 
Value: 1 
Inside do_variadic_thing 
Value: 1 
Inside do_variadic_thing 
Value: 4206337 
Inside do_variadic_thing 
Value: 4206337 

Я не понимаю, почему значение печататься изменениями после второго рекурсивного вызова в do_variadic_thing. Аргумент b реплицируется 3 раза; его тип также одинаков (т.е. Base<Value>). Кажется, что после второго вызова, аргументы больше не относятся к какой-либо действительной памяти.

Как это возможно?

ответ

3

Проход по ссылке:

void do_variadic_thing(const Base<Derived>& b, const Args&... args) 
                 ^
                 here 
+0

Спасибо. Я пропустил тот факт, что ссылка 'b' фактически передавалась как _copy_ для вариационной части. – madmann91

1

Вы передаете второй/третий экземпляры по значению - рассмотрите, как создаются копии.

+1

Также обратите внимание, что 'Base ' 'не' Value', оно не содержит поля 'i' (эта проблема называется« срезом объектов »). – kennytm

0

тип переменной b является Base<Value> const&, но объект это относится к относится к типу Value. Когда вы копируете b для его тиражирования do_thing, вы находитесь slicing it; то есть только копирование части Base<Value>.

 Смежные вопросы

  • Нет связанных вопросов^_^