How does std::list::swap() do this?

I just discovered this peculiar behavior of std::list that I don't completely understand. Lets assume I have the following code:
1
2
3
4
std::list<int> a;                               //legal
std::list<std::string> b;                       //legal
//std::list<const int> c;                       //Illegal!
std::list<std::pair<const int, std::string>> d; //...legal?? 


The part I don't understand is the last one. How come std::list can hold a pair that has a const value? Isn't one of the type requirements for std::list that the value has to be CopyAssignable? It clearly isn't:

1
2
std::pair<const int, std::string> my_pair{1,"my_pair"}, my_other_pair{2, "my_other_pair"};
//my_pair = my_other_pair; //ERROR 


So why does the following work?:
1
2
3
4
    std::list<std::pair<const int, std::string>> a, b;
    a.push_back({5,"ASDF"});
    b.push_back({7,"JKL;"});
    a.swap(b); //How come this works? 


Does it have something to do with how std::list's swap is implemented? I mean, since it is a linked list, is it just copying the pointers that are at the start and end of the list and exchanging them between both containers? Is that what is happening?
Last edited on
I don't normally use std::lists, so I did not know this beforehand, but I looked it up and, it says std::list::swap "Does not invoke any move, copy, or swap operations on individual elements."
https://en.cppreference.com/w/cpp/container/list/swap

So yes, it's doing something akin to swapping the root of each list and keeping everything else untouched, including each std::pair<const int, std::string>.
Last edited on
> std::list<const int> c; //Illegal!
> the value has to be CopyAssignable
I fail to see why the element should be assignable.
and with `emplace/move' since c++11, I fail to see why it should be copyable. (and constant are copyable)

gcc fails with «std::list must have a non-const, non-volatile value_type»
but I failt to see the rationale.


besides, you may "perfectly" do
1
2
struct foo{const int n;};
std::list<foo> a;
I noticed that too, but don't know enough to understand why that restriction is there.
It apparently is restricted by the allocator used? (Again, don't know.)
Last edited on
but I fail to see the rationale.

Something to do with the allocator. All std containers seem to blow up with const.

1
2
3
4
#include <vector>
int main() {
    std::vector<const int> v;  // no go
}

Topic archived. No new replies allowed.