https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64562
--- Comment #2 from splinterofchaos at gmail dot com --- Attempting a work-around on this problem... struct S { RETURN_TYPE operator--() && { return 1; } RETURN_TYPE operator--() const && { return 2; } template<class = std::enable_if_t<true>> RETURN_TYPE operator--() & { return 3; } template<class = std::enable_if_t<true>> RETURN_TYPE operator--() const & { return 4; } }; So, non-template functions have higher precedence, and I don't think it's valid to convert an S& to an S&& or const S&&. But in fact, gcc (at least, 4.9) ends up returning 1 for f3() and 2 for f4(). So, given an S&, it calls the S&& overload, and given a const S&, it calls the const S&& overload. clang, btw, does give the correct result, and rejects this code if you remove the & and const & overloads. So, this bug is maybe a bit bigger than ambiguity: gcc is picking an invalid overload, and /that/'s creating the ambiguity!