0

I have the following piece of code:

#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));
}

This code uses the Curiously Recurring Template Pattern define a compile-time polymorphic class with a method called print.

What I want to do is to run the print method from a function with a variable number of arguments (do_variadic_thing). The code provided above compiles, but produces a strange output:

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

I do not understand why the value printed changes after the second recursive call within do_variadic_thing. The argument b is replicated 3 times; its type is also the same (i.e Base<Value>). It seems that somehow, after the second call, the arguments no longer refer to some valid memory.

How is this possible?

3 Answers 3

3

Pass by reference:

void do_variadic_thing(const Base<Derived>& b, const Args&... args)
                                                         ^
                                                         here
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you. I missed the fact that the reference b was actually passed as a copy for the variadic part.
1

You are passing the second/third instances by value - consider how the copies are constructed.

1 Comment

Also note that Base<Value> is not Value, it does not contain the field i (this problem is called "object slicing").
0

The type of the variable b is Base<Value> const&, but the object it refers to is of type Value. When you copy b to replicate it inside do_thing, you are slicing it; that is, only copying the Base<Value> part.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.