const swap() 函数的目的是什么?
What's the purpose of const swap() function?
在实施自定义 tuple
(here), I found there is a wired swap()
function that takes const
parameters (cppreference) 时:
template< class... Types >
constexpr void swap( const std::tuple<Types...>& lhs,
const std::tuple<Types...>& rhs ) noexcept(/* see below */);
和一个 const 限定的 swap()
成员函数 (cppreference):
constexpr void swap( const tuple& other ) noexcept(/* see below */) const;
const
表示该对象是只读的,但是要交换两个对象,它必须修改对象,这违反了const
-ness。
那么,const swap() 函数的目的是什么?
您错过了有关重载何时可用的脚注:
This overload participates in overload resolution only if std::is_swappable_v<const Ti>
is true
for all i from 0 to sizeof...(Types)
.
如果您的类型 const_swappable
使得 swap(const const_swappable &, const const_swappable &)
合理,那么您没有理由不能交换 const std::tuple<const_swappable> &
.
例如,考虑一个 pointer-like 类型,它可以在不修改指针的情况下交换指针对象的值:
#include <type_traits>
#include <iostream>
struct foo {
int * x;
};
void swap(const foo& a, const foo& b){
std::swap(*a.x,*b.x);
};
int main(){
int a = 42;
int b = 3;
foo f1{&a};
foo f2{&b};
swap(f1,f2);
std::cout << "foo is const swappable: " << std::is_swappable_v<const foo> << "\n";
std::cout << *f1.x << "\n";
std::cout << *f2.x << "\n";
}
来自 cppreference 的注释:
- The program is ill-formed if
(std::is_swappable_v<const Types> && ...)
is not true
.
即:如果元组中的类型可以常量交换,则只能常量交换元组。
这是在“zip”提案中引入的 P2321 originally described in "A Plan for C++23 Ranges" P2214。
P2321
swap for const tuple and const pair. Once tuples of references are
made const-assignable, the default std::swap can be called for const
tuples of references. However, that triple-move swap does the wrong
thing:
int i = 1, j = 2;
const auto t1 = std::tie(i), t2 = std::tie(j);
// If std::swap(t1, t2); called the default triple-move std::swap then
// this would do
auto tmp = std::move(t1);
t1 = std::move(t2);
t2 = std::move(tmp);
// i == 2, j == 2
This paper therefore proposes adding overloads of swap for const
tuples and pairs to correctly perform element-wise swap.
P2214 解释了为什么 zip
的实现需要 const 可分配性。它源于赋值运算符没有被 ref 限定。
在实施自定义 tuple
(here), I found there is a wired swap()
function that takes const
parameters (cppreference) 时:
template< class... Types >
constexpr void swap( const std::tuple<Types...>& lhs,
const std::tuple<Types...>& rhs ) noexcept(/* see below */);
和一个 const 限定的 swap()
成员函数 (cppreference):
constexpr void swap( const tuple& other ) noexcept(/* see below */) const;
const
表示该对象是只读的,但是要交换两个对象,它必须修改对象,这违反了const
-ness。
那么,const swap() 函数的目的是什么?
您错过了有关重载何时可用的脚注:
This overload participates in overload resolution only if
std::is_swappable_v<const Ti>
istrue
for all i from 0 tosizeof...(Types)
.
如果您的类型 const_swappable
使得 swap(const const_swappable &, const const_swappable &)
合理,那么您没有理由不能交换 const std::tuple<const_swappable> &
.
例如,考虑一个 pointer-like 类型,它可以在不修改指针的情况下交换指针对象的值:
#include <type_traits>
#include <iostream>
struct foo {
int * x;
};
void swap(const foo& a, const foo& b){
std::swap(*a.x,*b.x);
};
int main(){
int a = 42;
int b = 3;
foo f1{&a};
foo f2{&b};
swap(f1,f2);
std::cout << "foo is const swappable: " << std::is_swappable_v<const foo> << "\n";
std::cout << *f1.x << "\n";
std::cout << *f2.x << "\n";
}
来自 cppreference 的注释:
- The program is ill-formed if
(std::is_swappable_v<const Types> && ...)
is nottrue
.
即:如果元组中的类型可以常量交换,则只能常量交换元组。
这是在“zip”提案中引入的 P2321 originally described in "A Plan for C++23 Ranges" P2214。
P2321
swap for const tuple and const pair. Once tuples of references are made const-assignable, the default std::swap can be called for const tuples of references. However, that triple-move swap does the wrong thing:
int i = 1, j = 2; const auto t1 = std::tie(i), t2 = std::tie(j); // If std::swap(t1, t2); called the default triple-move std::swap then // this would do auto tmp = std::move(t1); t1 = std::move(t2); t2 = std::move(tmp); // i == 2, j == 2
This paper therefore proposes adding overloads of swap for const tuples and pairs to correctly perform element-wise swap.
P2214 解释了为什么 zip
的实现需要 const 可分配性。它源于赋值运算符没有被 ref 限定。