C++17中Swappable要求与std::is_swappable<>是否等价?
问题分析与解答
代码示例
#include <type_traits> struct E { int x; E( ) = default; E(E&&) = delete; E& operator=(E&&) = delete; }; void swap(E& a, E& b) { /* Does NOT actually swap */ } int main(){ static_assert( std::is_swappable_v<E> ); }
问题背景与疑问
上述类E既非MoveConstructible也非MoveAssignable,因此无法使用<utility>库的swap()函数(C++17:23.2.3第3段)。用户定义了一个本地自定义swap()函数,但该函数并未实际执行交换操作。
在此场景下,类型特征std::is_swappable<>(C17:23.15.4.3)返回true,但根据C17:20.5.3.2第2段的Swappable要求:
对象t与u可交换当且仅当:
- 表达式swap(t, u)和swap(u, t)在指定上下文中求值时合法,且
- 这些表达式需满足以下效果:
- t引用的对象持有u原本的值,且
- u引用的对象持有t原本的值。
对于E类型的两个对象,swap(e1,e2)和swap(e2,e1)表达式合法,但不满足上述效果要求。请问std::is_swappable<>的含义是否与满足Swappable要求完全一致?还是编译器及<type_traits>库默认信任用户实现的自定义swap()符合要求?
解答
std::is_swappable<>的含义和Swappable要求并不完全一致,它仅做语法层面的合法性检查,不验证语义行为:
std::is_swappable_v<T>的核心判断逻辑是:在ADL(参数依赖查找)的上下文下,是否能合法调用swap操作。它只检查是否存在匹配的swap函数、参数传递是否符合语法要求,完全不关心swap函数内部的实际逻辑是否达成了交换对象值的效果。- 编译器和标准库无法在编译阶段验证用户自定义
swap的语义正确性,这属于运行时行为约束。标准库只会默认信任用户实现的swap会遵循Swappable的语义约定,但这种约定是程序员层面的规范,类型特征不会做任何验证。
简单来说:std::is_swappable<>保证swap表达式能编译通过,但不保证它真的能完成交换操作。
内容的提问来源于stack exchange,提问作者J L
相关产品推荐
相关产品推荐

