能否不依赖编译器内置函数实现is_nothrow_assignable?有无近似方案?
关于不依赖编译器内置实现
is_nothrow_assignable的问题 能否不依赖编译器内置函数完美实现?
无法完美实现。is_nothrow_assignable的核心是精准判断赋值操作是否无条件不抛出异常,这需要直接感知目标操作的异常规格——比如成员函数的noexcept修饰、内置类型赋值的固有特性等。而这些信息属于编译器对代码语义的内部分析范畴,仅靠用户层的模板元编程无法完全推导,因为C++标准并未提供让用户代码直接获取表达式异常属性的机制。
MSVC和LLVM选择用内置函数实现,正是因为该特性必须依赖编译器的语义分析能力;Boost没有提供非内置实现,也是受限于同样的技术瓶颈。
近似的Fallback方案
如果需要在极端场景下做降级处理,可以基于现有类型特性组合出近似实现,但要明确其局限性:
- 核心思路:先通过
std::is_assignable判断赋值操作是否可行,再结合std::is_nothrow_copy_assignable、std::is_nothrow_move_assignable以及内置类型的特殊规则,覆盖常见的noexcept赋值场景。 - 示例实现:
#include <type_traits> template <typename T, typename U> struct approximate_nothrow_assignable { private: // 内置类型的赋值均为nothrow static constexpr bool is_builtin = std::is_arithmetic_v<T> || std::is_pointer_v<T> || std::is_member_pointer_v<T>; // 先确认赋值操作可行 static constexpr bool is_assignable = std::is_assignable_v<T&, U>; // 匹配常见的nothrow赋值场景:拷贝/移动赋值 static constexpr bool has_nothrow_assign = (std::is_nothrow_copy_assignable_v<T> && std::is_same_v<U, T>) || (std::is_nothrow_move_assignable_v<T> && std::is_same_v<U, std::remove_reference_t<T>>); public: static constexpr bool value = is_builtin || (is_assignable && has_nothrow_assign); }; template <typename T, typename U> constexpr bool approximate_nothrow_assignable_v = approximate_nothrow_assignable<T, U>::value;
- 局限性说明:
- 无法覆盖自定义的非拷贝/移动赋值操作(比如
T& operator=(U),其中U既不是T也不是T的右值引用)的noexcept判断; - 对于带条件
noexcept的赋值操作(如noexcept(...)含表达式),无法区分其是否无条件不抛出,只能覆盖完全无条件的场景; - 部分用户自定义类型的
noexcept赋值操作可能被误判。
- 无法覆盖自定义的非拷贝/移动赋值操作(比如
总结
不存在不依赖编译器内置函数的完美实现方案,近似方案仅能覆盖常见场景,存在一定误判风险。若对准确性要求高,优先使用标准库提供的编译器内置实现;近似方案仅作为极端环境下的临时 fallback 选项。
内容的提问来源于stack exchange,提问作者埃博拉酱
相关产品推荐
相关产品推荐

