#include <unordered_map>
#include <vector>
class move_only
{public:
move_only() {}
move_only(move_only const&) = delete;
move_only& operator=(move_only const&) = delete;
move_only(move_only&&) = default;
move_only& operator=(move_only&&) = default;
};
typedef std::unordered_map<int, move_only> naked_map;
class wrapped_map
{public:
wrapped_map() {}
wrapped_map(wrapped_map const&) = delete;
wrapped_map& operator=(wrapped_map const&) = delete;
wrapped_map(wrapped_map&&) = default;
wrapped_map& operator=(wrapped_map&&) = default;
private:
naked_map m;
};
int main(int argc, char* argv[])
{ // The following fails to compile using -std=c++11 in GCC 4.7.2 and Clang 3.1.
// Their complaint is that std::pair<const int, move_only> has no copy
// constructor.
std::vector<naked_map> v1;
v1.resize(10); // won't compile
for (int i = 0; i != 10; ++i) {
v1.emplace_back(); // won't compile
}
// This compiles just fine, however, for both compilers.
std::vector<wrapped_map> v2;
v2.resize(10);
for (int i = 0; i != 10; ++i) {
v2.emplace_back();
}
}for (int i = 0; i != 10; ++i) {v1.emplace_back(); // won't compile}// This compiles just fine, however, for both compilers.std::vector<wrapped_map> v2;
v2.resize(10);for (int i = 0; i != 10; ++i) {v2.emplace_back();}}
--
On Nov 23, 2012, at 2:50 PM, Daniel Krügler <daniel....@gmail.com> wrote:Fwiw, I didn't read it as to only allow unconditional noexcept specifications.
> Problem is that there is no requirement that std::unordered_map is nothrow, if value *and* predicate *and* hasher are nothrow. In addition, in the absence of a corresponding standard requirement there is no clear leeway that an implementation *may* decide to add a *conditional* noexcept specification to that effect (17.6.5.12 allows "An implementation may strengthen the exception-specification
> for a non-virtual function by adding a non-throwing noexcept-specification." This can be read to only allow unconditional noexcept specifications).
The problem is partially a QoI and partially a Library specification problem. In principle you are right to expect that resize should be callable for a move-only value type. [...]
I would suggest to write up a proposal that adds the requirement that the container types shall have conditional move constructor/assignment operator noexcept-specifications to realize more move-only support.
std::vector<wrapped_map> v2;
This trick works, because for a non-copyinsertable type (see above quote) the implementation cannot fall back to copy-construction when move-construction may throw.
Dirk's code compiles with tip-of-trunk clang++/libc++.
[...]
Fwiw, all libc++ containers have a conditional noexcept on:
default constructor
move constructor
move assignment operator
swap