You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++20 requires约束中声明表达式泛型类型及std::same_as报错原因

问题根因

你遇到的报错是C++20 requires表达式的语法规则和std::stack的接口设计共同导致的,核心原因有两个:

  1. 标准库std::stack的pop()成员函数返回值类型为void,仅负责弹出栈顶元素,不会返回被弹出的元素值,访问栈顶元素需要调用top()接口,这是STL为了避免异常场景下元素丢失特意设计的惯例。
  2. C++20的requires表达式中,{ 表达式 } -> 概念<参数列表>的复合要求,会自动将decltype((表达式))的结果作为该概念的第一个模板实参,你写的参数列表会作为后续实参传入概念。
    std::same_as是需要两个类型参数的二元概念,std::same_as<A, B>表示A和B是完全相同的类型。你写的{ s.pop() } -> std::same_as<T>会被编译器自动展开为std::same_as<decltype((s.pop())), T>,由于s.pop()返回void,所以实际检查的约束就是std::same_as<void, T>,当你传入T为int时自然不满足,和报错信息完全对应。
关于替代写法的说明

你提到换成std::same_as<decltype(s.pop()), T>可以正常运行,这和语法逻辑是冲突的:decltype(s.pop())的结果依然是void,std::same_as<void, int>的判断结果仍然为假。大概率是你存在笔误:要么你实际约束的是top()接口而非pop(),要么你去掉了返回值检查仅保留了pop()可调用的要求。

正确的栈约束示例

如果你希望约束类型符合栈的通用接口,支持压入、弹出、获取栈顶元素,正确的约束可以写成:

#include <concepts>
#include <stack>
#include <type_traits>

template <typename S, typename T>
concept generic_stack = requires(S s, T t) {
    s.push(t);
    s.pop(); // 仅要求pop可调用,不检查返回值
    { s.top() } -> std::convertible_to<T>; // 检查栈顶元素可以转换为T
    // 如果要求严格类型一致可以用下面的写法
    // requires std::same_as<std::remove_cvref_t<decltype(s.top())>, T>;
};

template <typename T, generic_stack<T> S>
void compile_if_stack(S) {}

int main() {
    compile_if_stack<int>(std::stack<int>{}); // 编译通过
}

内容的提问来源于stack exchange,提问作者Kaihaku

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 00:09:05