17
votes

I'm trying to understand the conditions on std::swap from [C++11: utility.swap]. The template is defined as

template <typename T> void swap(T &, T &)

(plus some noexcept details) and as having the effect of "exchanging the values stored at the two locations".

Is the following program have well-defined?

#include <utility>

int main()
{
    int m, n;
    std::swap(m, n);
}

If I wrote swap code myself (i.e. int tmp = m; m = n; n = tmp;), it would have undefined behaviour, since it would attempt lvalue-to-rvalue conversion on an uninitialized object. But the standard std::swap function does not seem to come with any conditions imposed on it, nor can one derive from the specification that there is any lvalue-to-rvalue and thus UB.

Does the standard require std::swap to perform some magic that is well-defined on uninitialized objects?

To clarify the point, consider the function void f(int & n) { n = 25; }, which never has undefined behaviour (since it does not read from n).

2
Your program leaves m and n undefined before even calling swap. It's not swap's job to define them; both parameters to swap are expected to be defined. So I'm not seeing where the problem is.Mike DeSimone
Well at least for C++1y I would say that for sure using and indeterminate int would be undefined. I don't think anything swap could do would change that. I would probably say the intention for C++11 was probably the same. The only exception would be in the case of unsigned narrow chars which would retain their indeterminate values.Shafik Yaghmour
@MikeDeSimone: well, it's just kind of impossible to implement, as you can see from my example attempt... And where does it say that "both parameters are expected to be defined"?Kerrek SB
@ShafikYaghmour: So does std::swap mandate library magic, or is it missing a condition?Kerrek SB
@ShafikYaghmour: I don't follow... please see my update. The problem does not manifest at the call site; f(a) is perfectly valid.Kerrek SB

2 Answers

12
votes

Very nice question. However, I would say this is covered by [res.on.arguments]§1:

Each of the following applies to all arguments to functions defined in the C++ standard library, unless explicitly stated otherwise.

  • If an argument to a function has an invalid value (such as a value outside the domain of the function or a pointer invalid for its intended use), the behavior is undefined.

To address your concern about f(n), the function f from your question is not a part of the C++ standard library and thus the above clause does not apply to it.

1
votes

As the value of M is undefined, I would expect it to taint the call to swap. Nasal Demons may fly, when swap is called.