如何判断函数为非void类型?我的C++ Concept验证代码为何失效?
问题分析与解决
你的Concept实现逻辑存在错误:requires表达式中直接放置编译期布尔值时,仅会检查该布尔表达式是否合法编译,而非其值的真假。
对于你的bad结构体,t.operator[](val)是合法可调用的,因此decltype(t.operator[](val))能正确推导为void,进而!std::is_same<decltype(t.operator[](val)), void>::value这个表达式本身是合法的(尽管它的值是false),所以整个requires子句会被判定为满足,最终导致Indexable<bad>被错误地认为是true。
而std::map的测试能通过,只是因为其operator[]返回非void类型,此时布尔表达式的值为true,恰好符合预期,但这只是巧合,并非你的Concept逻辑正确。
正确的实现方式
你需要同时满足两个条件:
- 类型
T支持operator[]调用(即t[val]表达式合法) operator[]的返回值类型不是void
以下是两种可靠的实现:
方式1:使用返回类型约束
#include <type_traits> #include <map> template<class T> concept Indexable = requires(T t, size_t val){ // 约束operator[]的返回类型非void { t[val] } -> std::negation<std::is_void>; };
方式2:嵌套requires条件检查
#include <type_traits> #include <map> template<class T> concept Indexable = requires(T t, size_t val){ // 先确保operator[]可调用 t[val]; // 再检查返回值非void requires !std::is_void_v<decltype(t[val])>; };
测试验证
测试返回void的结构体
struct bad { void operator[](size_t) {} }; static_assert(!Indexable<bad>, "fail"); // 现在正常通过断言
测试std::map
static_assert(Indexable<std::map<int, std::string>>, "fail"); // 正常通过断言
内容的提问来源于stack exchange,提问作者Nikolai
相关产品推荐
相关产品推荐

