🔴 🟡 🟢CppOnline26 Quiz Hunt
← Back to Posts

CppOnline26 Quiz Hunt

I had great fun attending the CppOnline conference and going through the Gathertown space to find and solve as many questions as I could. I ended up placing 2nd on the leaderboard (and still got the prize anyway, since 1st already had a CLion license!), and there was just one question I couldn't find for the life of me. I asked and was told after the fact that the last question was in a hidden coffee cup as you leave the lobby to go to the poster room, and could only be interacted with in a specific position. Though the Gathertown space is no longer accessible, the following is everything I found with location screenshots, in the order I found them in. I quite enjoyed finding all the Easter eggs and hidden rooms in the space, and I hope reading through this can bring you a sliver of the fun I experienced while hunting these locations down! I certainly also learned I need to refresh my understanding of move semantics, so expect a post soon about that.


  1. Location: main hall billiard ball on tableScreenshot 2026-03-12 at 9.50.04 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    #include <map>
    
    bool default_constructed = false;
    bool constructed = false;
    bool assigned = false;
    
    class C {
    public:
    	C() { default_constructed = true; }
    	C(int) { constructed = true; }
    	C& operator=(const C&) { assigned = true; return *this;}
    };
    
    int main() {
    	std::map<int, C> m;
    	m[7] = C(1);
    
    	std::cout << default_constructed << constructed << assigned;
    }

Answer: 111

Solution: m[7] looks for the key 7 and doesn't find it, so std::map::operator[] value initializes a C object via the default constructor and returns a reference. Then the right hand side, C(1) explicitly calls the parameterized constructor and gives a temporary C(1), and the = operator takes that temporary to overwrite the default-constructed C from the left hand side. As an aside, std::map::try_emplace (C++17) and std::map::emplace (C++11) can construct the object directly in the map's memory without needing to make a temporary copy: std::map::emplace (C++11) is clunkier because std::map expects a std::pair<const Key, Value>, so to really avoid temporaries you have to go piecewise:

m.emplace(std::piecewise_construct, std::forward_as_tuple(7), std::forward_as_tuple(1));

std::map::try_emplace (C++17) checks if the key exists first. If it does, the constructor arguments aren't looked at; if it doesn't, then the value is constructed in place:

m.try_emplace(7, 1);

This is CppQuiz question #208.

  1. Location: Social room, thing next to Booking objectScreenshot 2026-03-12 at 9.51.33 PM.pngQuestion: According to the C++23 standard, what is the output of this program?
    #include <iostream>
    
    class A
    {
    public:
    	A() { std::cout << "A"; }
    	A(const A &) { std::cout << "a"; }
    };
    
    class B: public virtual A
    {
    public:
    	B() { std::cout << "B"; }
    	B(const B &) { std::cout << "b"; }
    };
    
    class C: public virtual A
    {
    public:
    	C() { std::cout << "C"; }
    	C(const C &) { std::cout << "c"; }
    };
    
    class D: B, C
    {
    public:
    	D() { std::cout << "D"; }
    	D(const D &) { std::cout << "d"; }
    };
    
    int main()
    {
    	D d1;
    	D d2(d1);
    }

Answer: ABCDABCd

Solution: The order of virtual inheritance initialization happens as such: The most derived class is responsible for initializing the virtual base, and then the direct bases are initialized in the order they are declared, and then the body of the most derived class's constructor runs. So in the case of D d1;, the outputs would be ABCD in that order. Then for d2 copy construction: D(const D&) gets called, but this copy constructor doesn't explicitly initialize the base classes in the initializer list, so the compiler will default to calling the default constructors of the bases. Thus, the second set of outputs is ABCd. Aside: If you wanted, e.g., ABCDabcd, you'd need to explicitly chain together copy constructors like so: D(const D &other) : A(other), B(other), C(other) { std::cout << "d"; }. Note that the ordering of abcd is still defined by class definition, not initializer list order, due to virtual inheritance. In a normal hierarchy, B would initialize A, etc.

  1. Location: Upper right lightning talk corner in lobbyScreenshot 2026-03-12 at 11.34.23 PM.pngQuestion: What is the guaranteed output of this program?
    #include <iostream>
    
    struct Base {
    	virtual int f() = 0;
    };
    
    int Base::f() { return 1; }
    
    struct Derived : Base {
    	int f() override;
    };
    
    int Derived::f() { return 2; }
    
    int main() {
    	Derived object;
    	std::cout << object.f();
    	std::cout << ((Base&)object).f();
    }

Answer: 22

Solution: The first line will return 2, as Derived's f() function will be called. Easy enough. The second line is trying to access the same object through its base class, Base. Since Base's f() function is virtual, the dynamic type of object is what determines which f() gets called via dynamic dispatch, so it's still the Derived::f(). Notice that the pure virtual function in Base is still defined, but will never be called due to polymorphism. This is in fact valid by the standard. If you wanted to force the Base version of the function, use the scope resolution operator: object.Base::f(). This static binding (call-by-name) requires the function to be declared in the Base class but defined outside the class (due to lexical rules, but also best practices), and is still subject to access control (can't be marked private). This is Cpp Quiz Question #224.

  1. Location: Poster room bottom training section, beersScreenshot 2026-03-12 at 11.29.37 PM.pngQuestion: According to the C++23 standard, what is the output of this program?
    #include <iostream>
    #include <type_traits>
    #include <utility>
    
    void g(int&) { std::cout << 'L'; }
    void g(int&&) { std::cout << 'R'; }
    
    template
    void f(T&& t) {
    	if (std::is_same_v<T, int>) { std::cout << 1; }
    	if (std::is_same_v<T, int&>) { std::cout << 2; }
    	if (std::is_same_v<T, int&&>) { std::cout << 3; }
    	g(std::forward(t));
    }
    
    int main() {
    	f(42);
    	int i = 0;
    	f(i);
    }

Answer: 1R2L

Solution: This is looking at forwarding/universal references and reference collapsing. 42 is an rvalue and the f(42) call is only comparing std::is_same_v<int, int> in the first part. Then std::forward casts 42 to original rvalue status, which matches g(int&&), printing 1R. In the f(i) call, i is an lvalue. If you pass an lvalue to a forwarding reference T&&, the compiler uses template argument deduction and deduces T itself as an lvalue reference int&, so only std::is_same_v<int&, int&> is true. Then std::forward(t) turns T&& to int& &&, and under reference collapsing rules & + && = &, so this becomes int& and 2L is printed. As an aside, had i been const, no numbers or letters would've printed (the const-ness carries through the template argument deduction and reference collapsing).

  1. Location: track B room, bottom right corner plantScreenshot 2026-03-12 at 11.36.45 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    namespace x {
    	class C {};
    	void f(const C& i) {
    		std::cout << "1";
    	}
    }
    
    namespace y {
    	void f(const x::C& i) {
    		std::cout << "2";
    	}
    }
    
    int main() {
    	f(x::C());
    }

Answer: 1

Solution: This is looking at argument-dependent lookup (Koenig lookup). When f(x::C()) is called, there's no namespace specified to look for f in, and f isn't defined globally. Normally the compiler would stop there, but since C is defined in the x namespace (x::C()), ADL also tells the compiler to search x for any functions matching f. The compiler has zero reason to look inside the namespace y, because it hasn't been brought into scope with a using directive, nor is the argument associated with that namespace. This is CppQuiz question #196.

  1. Location: secret room, right side column of 4 food stands, bottom food standScreenshot 2026-03-12 at 9.58.09 PM.pngScreenshot 2026-03-12 at 9.59.35 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    int j = 1;
    
    int main() {
    	int& i = j, j;
    	j = 2;
    	std::cout << i << j;
    }

Answer: 12

Solution: In int& i = j, j; there are two things going on: first int& i = j creates a reference i and aliases it to the global j. Then j; declares a local j for the scope of the main function that shadows the global j. So when j = 2; happens, the reference i is still pointing to the global j with value 1, and the local j gets initialized to 2. So the printout is 12. Had we used ::j = 2 instead, the global j would've been updated while the local j was still initialized.

  1. Location: secret room, hidden private room on the bottomScreenshot 2026-03-12 at 10.08.57 PM.pngQuestion: According to the C++23 standard, what is the output of this program?
    #include <iostream>
    
    using namespace std;
    
    int main() {
        int a = '0';
        char const &b = a;
        cout << b;
        a++;
        cout << b;
    }

Answer: 00

Solution: We need to be careful thinking about these references to different types. a is an int and gets set to the ASCII value of 0 which is 48, but b is a char, so the compiler can't directly point the reference b to the memory location of a. Instead, the compiler does an implicit conversion, copying the value of a into a temporary char and binding the reference b to that. Since b is const, the lifetime of that temporary is implicitly extended to the lifetime of b. Then when a is incremented, the temp that b points to is unchanged, so printing b both times still refers to that temporary char 0.

  1. Location: secret room, glowing character hologram near centerScreenshot 2026-03-12 at 10.04.07 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    enum A : const int volatile { x, y, z };
    
    int main() {
    	A a = A::x;
    	a = A::y;
    	std::cout << "ok";
    }

Answer: ok

Solution: The enum A has an underlying int definition. Reassigning a from A::x to A::y is fine and everything compiles. You may think the cv-qualified enum definition makes the enum invalid or unassignable, but it still behaves as a normal enum.

  1. Location: secret room, top left, interact with the mic on stage (Dutch meetup question!)Screenshot 2026-03-12 at 10.04.42 PM.pngQuestion: This C++ Hello World program doesn't seem to print anything. If you could only insert one keyword, which one can be used to fix it?
    #include <iostream>
    
    class Base {
    public:
        ~Base() { }
    };
    
    class Derived : public Base {
    public:
        ~Derived() { std::cout << "Hello world!" << std::endl; }
    };
    
    int main() {
        Base* b = new Derived();
        delete b;
        return 0;
    }

Answer: virtual

Solution: Deletion is happening through a base class pointer (aka polymorphically), so it needs a virtual destructor virtual ~Base(). Then delete b; will run Derived::~Derived() and Base::~Base() as expected.

  1. Location: secret room, left side bottom traffic cone (Dutch meetup question)Screenshot 2026-03-12 at 10.05.35 PM.pngQuestion: What does the code below output?
    #include <iostream>
    
    int main() {
        int x = 10;
        int y = x++ + ++x;
        std::cout << y << std::endl;
        return 0;
    }

Answer: UB

Solution: I originally entered 22 (and this was accepted as an answer!) because I thought that y would be summing 11 from x++ and then 11 from ++x (and then x would end up as 12), but I actually now think this might be UB as it's not clear what the sequence of modifications on x should be. In fact, I think this is unsequenced (as opposed to indeterminately sequenced) because + doesn't impose any evaluation order between the side effects from the left and right operands. Indeterminately sequenced means one side is guaranteed to happen before the other, but the standard doesn't say which one. That doesn't hold here in the built-in + operator case.

  1. Location: secret room, hidden top side of left small building near spawn pointScreenshot 2026-03-12 at 10.01.02 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <future>
    #include <iostream>
    
    int main()
    {
        try {
            std::promise p;
            std::future f1 = p.get_future();
            std::future f2 = p.get_future();
            p.set_value(1);
            std::cout << f1.get() << f2.get();
        } catch(const std::exception& e)
        {
            std::cout << 2;
        }
    }

Answer: 2

Solution: This is missing that template argument and should look like std::promise p; but with that, this would print 2. p.get_future() can only be called once per promise, so the second call std::future f2 = p.get_future() throws a std::future_error (std::future_already_retrieved).

  1. Location: hallway between lobby and outside, first wall tile on rightScreenshot 2026-03-12 at 9.53.09 PM.pngQuestion: According to the C++23 standard, what is the output of this program?
    #include <variant>
    #include <iostream>
    
    int main() {
        std::variant<int, double, char> v;
        std::cout << v.index();
    }

Answer: 0

Solution: A default-constructed variant holds its first alternative (int here), and index() returns the zero-based index of the held alternative.

  1. Location: secret room, ramen bowl on left side of right ramen shack, next to the two buildings near spawn pointScreenshot 2026-03-12 at 10.02.15 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    int main() {
        int i = 1;
        int const& a = i > 0 ? i : 1;
        i = 2;
        std::cout << i << a;
    }

Answer: 21

Solution: i > 0 is true, so you would think the reference a gets pointed to the memory location of i, so 22 gets printed. But actually, in the ternary operator, since the left side i is an lvalue (int object) and the right side 1 is a prvalue (int temporary), the compiler needs to choose one of these to be the common result of the ternary. It chooses prvalue because that's the "greatest common factor" when one side is a reference and one is a value. So int const& ends up binding to a temporary copy, leading to the printout of 21. If both branches of the ternary were lvalues, lvalue-ness would be preserved.

  1. Location: secret room balcony, entered through top left of main room, via elevators behind folding screen, bottom left corner of balconyScreenshot 2026-03-12 at 11.40.33 PM.pngScreenshot 2026-03-12 at 11.40.58 PM.pngScreenshot 2026-03-12 at 11.41.26 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    class A {
    public:
    	virtual void f() { std::cout << "A"; }
    };
    
    class B : public A {
    public:
    	void f() { std::cout << "B"; }
    };
    
    void g(A a) { a.f(); }
    
    int main() {
    	B b;
    	g(b);
    }

Answer: A

Solution: g(A a) takes the parameter by value, so the g(b) call copies the base subobject A from b. This is object slicing. Inside g, we have an A object, so virtual dispatch uses that dynamic type, and A::f() runs.

  1. Location: secret room, fireplace near bottom leftScreenshot 2026-03-12 at 10.06.23 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    struct A {
    	virtual std::ostream &put(std::ostream &o) const {
    		return o << 'A';
    	}
    };
    
    struct B : A {
    	virtual std::ostream &put(std::ostream &o) const {
    		return o << 'B';
    	}
    };
    
    std::ostream &operator<<(std::ostream &o, const A &a) {
    	return a.put(o);
    }
    
    int main() {
    	B b;
    	std::cout << b;
    }

Answer: B

Solution: std::cout << b calls the &operator<<(std::ostream &o, const A &a) because b is-a A (is a subtype of). Then at the virtual a.put(o) call the dynamic type of a here is B, so dispatch chooses B::put.

  1. Location: Track C room, sparkly out of place floor cushion above HRT sponsor tile (Dutch meetup question)Screenshot 2026-03-12 at 11.35.49 PM.pngQuestion: Which of these functions does not exist in the C++ Standard? A. std::get_money() B. std::set_money() C. std::put_money() D. std::money_put()

Answer: B

Solution: get_money() and put_money() are input/output manipulators for money values, and money_put() is a locale facet operator (it uses the locale to format for money output operations). Usually you wouldn't call this directly (instead use put_money()). I actually had no idea C++ standard library (and most other languages) had built-in support for money values by locale, so this was a cool question for me!

  1. Location: Track A room, right side plant (near hallway to B)Screenshot 2026-03-12 at 11.39.24 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    struct E
    {
    	E() { std::cout << "1"; }
    	E(const E&) { std::cout << "2"; }
    	~E() { std::cout << "3"; }
    };
    
    E f()
    {
    	return E();
    }
    
    int main()
    {
    	f();
    }

Answer: 13

Solution: Since C++17, when a prvalue of type T initializes a T object directly, the object is constructed in its final storage (copy elision is guaranteed). Hence, no copy/move constructors are called and 2 is never printed. 1 is printed at construction time and 3 is printed at the end of f() in main when the E object is destroyed.

  1. Location: Alber Blanc sponsorship booth in lobby, drink on desk in top leftScreenshot 2026-03-12 at 9.50.56 PM.pngQuestion: According to the C++ standard, what is the guaranteed output of this program?
    #include <iostream>
    #include <utility>
    
    class C
    {
    public:
        C(){}
        C(const C&){} // User-declared, disables move constructor
    };
    
    int main()
    {
        C c;
        C c2(std::move(c));
        std::cout << "ok";
    }

Answer: ok

Solution: As the comment says, since a copy constructor is declared, the implicit move constructor isn't generated. But that's fine, because the std::move(c) doesn't force a move by itself, it just casts c to an rvalue. So the C c2(std::move(c)) call uses the copy constructor, since a const lvalue can bind to an rvalue. Everything is fine and well and compiles.

  1. Location: Lobby, fourth stool to the right from the merch counter in the rightwards seating areaScreenshot 2026-03-12 at 9.48.47 PM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    int main() {
    	int a = 10;
    	int b = 20;
    	int x;
    	x = a, b;
    	std::cout << x;
    }

Answer: 10

Solution: The comma operator takes precedence over =, so the x = a, b; expression statement parses as an assignment of a to x, and then an expression of b. So x is set to 10 and then b is evaluated and discarded.

  1. Location: secret room, top right far corner, store doorScreenshot 2026-03-13 at 12.09.42 AM.pngQuestion: According to the C++23 standard, what is the output of this program?
    #include <iostream>
    
    int main() {
        int I = 1, J = 1, K = 1;
        std::cout << (++I || ++J && ++K);
        std::cout << I << J << K;
    }

Answer: 1211

Solution: First I, J, K are all separately initialized to 1. Then the key thing to note is that && takes precedence over ||, so the logical expression is parsed as ++I || (++J && ++K). ++I is evaluated first from the left and makes I = 2 which is nonzero and truthy. That leads to short-circuiting, and (++J && ++K) is never touched. So 1 is printed as the boolean result, and the values of I, J, K are 2, 1, 1 respectively.

  1. Location: secret room, left wall near top, between two buildingsScreenshot 2026-03-13 at 12.18.35 AM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    #include <map>
    using namespace std;
    
    int main()
    {
    	map<bool,int> mb = {{1,2},{3,4},{5,0}};
    	cout << mb.size();
    	map<int,int> mi = {{1,2},{3,4},{5,0}};
    	cout << mi.size();
    }

Answer: 13

Solution: In the map mb, the keys 1, 3, 5 all convert to true. But map keys are unique, so only one value remains for true (the 0 value), and the size of that map is 1. mi functions as you'd expect -- all keys are different and map to those corresponding values. So mi's size is 3.

  1. Location: secret room, under a roof near bottom left side, only accessible from the north (Dutch meetup question)Screenshot 2026-03-13 at 12.48.03 AM.pngQuestion: This program doesn't compile. If you could only insert one keyword, what could be used to fix the code?
    #include <iostream>
    
    class MyClass {
    private:
        int x;
    public:
        MyClass(int val) : x(val) {}
        void setX(int val) const { x = val; }
        int getX() const { return x; }
    };

Answer: mutable

Solution: If we want to intentionally allow the const function setX to mutate x we need to mark xas mutable. The reason we might want to use the const/mutable pair here (as opposed to no qualifiers at all) is as a way to enforce defaulting to const-correctness and use mutable only for deliberate, narrow exceptions.

  1. Location: onboarding room, top right arrowScreenshot 2026-03-13 at 1.46.51 AM.pngQuestion: According to the C++23 standard, what is the guaranteed output of this program?
    #include <iostream>
    
    int main() {
    	char* a = const_cast<char*>("Hello");
    	a[4] = '\0';
    	std::cout << a;
    }

Answer: UB

Solution: The string literal "Hello" is stored in read-only memory on most systems. The const_cast<char*> only modifies the type. It doesn't actually make the underlying storage writable. Then trying to modify via a[4] = '\0' might crash, appear to print Hell, or do something else unpredictable. The safe way is to use a real writable array char a[] = "Hello"; or to use a std::string.