为何C++20的concept约束未按预期生效?重载Foo调用歧义
为什么互斥约束的Foo重载会出现调用歧义?
问题出在你对C++20约束的写法可能存在逻辑错误,导致两个重载的约束并没有真正互斥:
如果你的第一个重载把「T不是枚举类型」的判断写在了
requires表达式内部,比如这样:template<typename T> requires requires(T t) { !std::is_enum_v<T>; // 错误:这里只检查表达式是否合法,不检查值是否为true {std::to_string(t)} -> std::same_as<std::string>; } void Foo(T t) {}C++的
requires表达式只会验证内部的表达式是否可编译,不会判断表达式的返回值是否为true。!std::is_enum_v<T>本身是一个合法的布尔表达式(无论T是不是枚举,这个表达式都能编译通过),所以当T是枚举类型时,第一个重载的约束会被判定为满足,而第二个重载的std::is_enum_v<T>约束也满足,自然就出现了调用歧义。正确的写法应该是把「T不是枚举类型」作为独立条件,和
requires表达式做逻辑与,确保只有当T不是枚举且std::to_string(t)返回std::string时,第一个重载才满足约束:template<typename T> requires (!std::is_enum_v<T> && requires(T t) { {std::to_string(t)} -> std::same_as<std::string>; }) void Foo(T t) {}这种情况下,当T是枚举类型时,
!std::is_enum_v<T>为false,整个约束直接不满足,第一个重载会被排除,调用时只会匹配第二个重载,不会有歧义。
补充说明:当T是枚举类型时,std::to_string(t)能通过编译,是因为枚举可以隐式转换为整数类型,调用了std::to_string的整数重载,返回值确实是std::string——这也是约束写错时,第一个重载的requires表达式会被判定为合法的原因。
内容的提问来源于stack exchange,提问作者xmllmx
相关产品推荐
相关产品推荐

