Is there a more convenient (less key-strokes) way to quickly dump a few variables to stdout in C++?
I would have to say No, not in the language. But I do not consider std::cout a challenging amount to type.
You can tryout the template methods provided by other answer's.
But you should try GDB (or some debugger available on your system). GDB can 'dump' automatic variables with no _effort_ at all, as automatic var's for the current stack frame are always kept up-to-date in the "Locals" window.
Or do C++ people just always define their own simple print function or something?
No, or maybe something.
I use std::cout and std::cerr (as defined) for lots of debugging, but not in the 'how can I save the most typing' frame of mind.
My view is that creating a 'convenience' (i.e. not required) function is appropriate for doing something you wish to repeat. My rule of thumb is 3 times ... if I do a particular something 3 (or more) times (like generate a std::cout statement with the same or similar variables in it) then I might write a function (rather than copy the line) for that repeated effort.
Typically, I use one of two (what I call) disposable debug methods ... and most of my objects also have both show() and dump(), and there can be multiple show/dump functions or methods, each with different signatures, and default values.
if(dbg1) show(a,b,c,d,e);
if(dbg1b) show(b);
// etc
and
if(dbg2) dump(a,b,c,d,e);
Show typically uses and does what what std::cout provides, and little else.
Dump does what show does, but also might provide an alternate view of the data, either hex or binary translations of the values, or perhaps tables. What ever helps.
Disposable does not mean I will dispose of them, but rather I might, and I often get tired of output that does not change, so I set dbgX to false when this code seems to be working, at least until I decide to dispose of the debug invocation.
But then, you do have to implement each of the functions and methods, and yes, you are going to have to learn to type.
If these variables are automatic, you should know that the debugger GDB automatically displays them in a window called "Locals", and keeps them up-to-date during single step.
In GDB, object instance contents can often be displayed with "p *obj", and there are ways to add a particular obj name to the local display window.
It does not take a lot to run GDB. If you object to creating the 80 char std::cout code above, it takes far less typing to launch GDB, set break in main, and run the simple task under gdb control, (then single step to observe these variables at any step in your code) not just where you happened to insert a show() or dump() command.
And if you have GDB, you can also command to print using "p show()" (when the show() function is in scope) to see what the in-scope variables look like to std::cout (if you don't believe the "Locals" window).
GDB allows you to "p this->show()" when stepping through a method of the instance, or "p myObj->show()" when the myObj is accessible.
ALso, "p *this" and "p *myObj" will provide a default, typically useful, display of the current contents your object.
Anyway. Yes you can always work hard to shorten your typing effort.