When for the first time I learned C++, I used to practise guessing what goes wrong when the compiler issues errors. Basically, I jumped to the line where the error is spotted and, without reading further error message, tried to deduce the mistake just by looking at the code. I found that this is quite effective (but not efficient, do not do this for in real-world because you will waste lots of your time) to understand many advanced programming caveats. I even always recommend it to C/C++ newbie who has the guts to do so. Up to certain points, you can even start to understand the distinct behaviors of different type of compilers.
Often, time does not permit me to do this kind of exercises anymore. So instead of "talking" to the compiler directly, now from time to time I just drop Gimpel Software's bug of the month a visit. Some of them can be quite inspiring, and it is always fascinating to try to get the bug in matter of seconds. Try it yourself.