Actually, you did remind me that I did run into a type inference bug: the original ScopeGuard implementation ( http://www.drdobbs.com/cpp/generic-change-the-way-you-write-... ) relies on binding a temporary object to a const reference to guarantee that the destructor doesn't get elided. So changing ScopeGuard foo = MakeGuard(...) to auto foo = MakeGuard(...) does change the meaning of the code, and you may have the cleanup code optimized away.
So, yes, I'll concede that code that expects you to cast some kind of proxy type to a different type (e.g., the vector<bool> example, or the original ScopeGuard, or perhaps valarray) isn't ready for type inference. But that kind of code is pretty rare, so the list of exceptions to the rule should be short.
Besides, if you want to swap two elements, use std::swap.
Correction: given a vector<bool> foo, "std::swap(foo[0], foo[1])" won't compile because std::swap takes parameters as non-const references, i.e., not temporaries (given a vector<int> bar, "std::swap(bar[0], bar[1])" won't compile either); so you have to use "std::iter_swap(foo.begin(), foo.begin + 1)" to (correctly) swap the first two elements.
And another correction: given a vector<int> bar, "std::swap(bar[0], bar[1])" does compile fine. All vectors other than vector<bool> return modifiable references when elements are accessed with square brackets.
An updated version of ScopeGuard doesn't have this problem ( https://github.com/facebook/folly/blob/master/folly/ScopeGua... ).
So, yes, I'll concede that code that expects you to cast some kind of proxy type to a different type (e.g., the vector<bool> example, or the original ScopeGuard, or perhaps valarray) isn't ready for type inference. But that kind of code is pretty rare, so the list of exceptions to the rule should be short.
Besides, if you want to swap two elements, use std::swap.