如何结合Concepts与deducing this验证const对象不可用+=?
如何在使用C++ "deducing this"时正确验证const对象无法执行加法赋值?
问题根源
你的代码中,Y的模板化operator+=会在传入const Y&时,被编译器推导实例化出const Y& operator+=(const Y& self, int)的重载。虽然这个函数的函数体里修改const成员会导致实际调用失败,但Concept的requires表达式仅检查重载决议是否成功、返回类型是否匹配,不会验证函数体的编译正确性。因此has_addition_assignment<const Y&, int>会被误判为满足条件,导致static_assert失败。
解决方案
有两种可行的修复方向,根据你的场景选择即可:
方案1:约束operator+=模板,拒绝const类型的Self
直接修改Y的operator+=,添加requires约束确保Self不是const类型,从源头上避免为const对象生成无效重载:
#include <concepts> #include <type_traits> struct Y { Y() = default; template<typename Self> requires (!std::is_const_v<Self>) // 新增约束:Self不能是const类型 Self& operator+=(this Self& self, int x) { self.value += x; return self; } int value = 0; };
此时当传入const Y&时,模板不会被实例化,const Y&找不到对应的operator+=,has_addition_assignment<const Y&, int>会正确返回false。
方案2:修正Concept,排除const引用类型
如果无法修改Y的定义,可以在has_addition_assignment中新增检查,确保引用的对象是非const的:
#include <concepts> #include <type_traits> template<typename T, typename U> concept has_addition_assignment = std::is_lvalue_reference_v<T> && !std::is_const_v<std::remove_reference_t<T>> // 新增:过滤const引用 && requires(T a, U b) { { a += b } -> std::same_as<T>; };
这样即使Y的operator+=能被const Y&实例化,Concept也会直接判定该类型不满足条件。
验证效果
无论使用哪种方案,static_assert(!has_addition_assignment<const Y&, int>);都能正常通过,同时const Y y; y += 1;依然会编译失败,完全符合你的预期。
内容的提问来源于stack exchange,提问作者Derek
相关产品推荐
相关产品推荐

