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

基于Clang库检查C++类是否满足Concept约束的技术咨询

问题描述

我编写了一段解析C++声明(类、模板类、函数、Concept)的代码,希望判断指定类是否满足某一Concept的约束要求,若不满足则指出未达标的约束项。但自行实现的CheckConceptUsage函数始终返回false,即使类符合Concept要求。现寻求使用Clang Sema分析Concept的示例,以下是我的实现代码:

实现代码
void CheckConceptUsage(Sema &SemaRef, const ConceptDecl *Concept, const CXXRecordDecl *Class) {
    // Get the type of the class.
    QualType ClassType = SemaRef.Context.getRecordType(Class);

    // Create a TemplateArgument representing the class type.
    TemplateArgument ClassTemplateArg(ClassType);

    // Prepare the necessary data structures for the constraint check.
    ConstraintSatisfaction Satisfaction;

    // Create a MultiLevelTemplateArgumentList
    MultiLevelTemplateArgumentList TemplateArgs;
     ArrayRef<TemplateArgument> TemplateArgsRef(ClassTemplateArg);
    TemplateArgs.addOuterTemplateArguments(const_cast<CXXRecordDecl *>(Class), TemplateArgsRef, /*Final*/ true);
    // TemplateArgs.addOuterTemplateArguments(ArrayRef<TemplateArgument>(ClassTemplateArg));


    // Retrieve the constraint expression associated with the concept
    const Expr *ConstraintExpr = Concept->getConstraintExpr();
    
    if (!ConstraintExpr) {
        llvm::outs() << "The concept " << Concept->getNameAsString() 
                     << " has no constraints (requires clause) to check.\n";
        return;
    }

    // Cast the constraint expression to RequiresExpr to access its components
    if (const RequiresExpr *ReqExpr = llvm::dyn_cast<RequiresExpr>(ConstraintExpr)) {
        std::cout << "--- CheckConceptUsage if " << std::endl;
        // Get the list of requirements (constraints) in the requires expression
        llvm::SmallVector<const Expr*, 4> ConstraintExprs;

        for (const auto &Requirement : ReqExpr->getRequirements()) {
            std::cout << "--- CheckConceptUsage for " << std::endl;
            if (const auto *ExprReq = llvm::dyn_cast<clang::concepts::ExprRequirement>(Requirement)) {
                // Handle expression requirements
                std::cout << "--- CheckConceptUsage ExprRequirement" << std::endl;
                ConstraintExprs.push_back(ExprReq->getExpr());
            } else if (const auto *TypeReq = llvm::dyn_cast<clang::concepts::TypeRequirement>(Requirement)) {
                // Handle type requirements by evaluating the type's instantiation dependency
                std::cout << "--- CheckConceptUsage TypeRequirement" << std::endl;
                QualType Type = TypeReq->getType()->getType();
                QualType DependentType = TypeReq->getType()->getType();
                if (Type->isDependentType()) {
                    std::cout << "--- CheckConceptUsage isDependentType" << std::endl;
                    // Create a pseudo-expression that checks if this type exists
                    // TypeTraitExpr *TraitExpr = TypeTraitExpr::Create(
                    //     SemaRef.Context, 
                    //     DependentType,
                    //     SourceLocation(), 
                    //     UTT_IsCompleteType,  // Use a type trait like "is complete type"
                    //     ArrayRef<QualType>(DependentType),
                    //     SourceLocation(), 
                    //     SemaRef.Context.BoolTy
                    // );
                    
                    // ConstraintExprs.push_back(TraitExpr);
                }
            }
        }

        
        std::cout << "--- CheckConceptUsage ConstraintExprs size:" << ConstraintExprs.size() << std::endl;

        // Now use the updated list of constraints in the satisfaction check
        bool IsSatisfied = SemaRef.CheckConstraintSatisfaction(
            Concept, 
            ConstraintExprs, 
            TemplateArgs, 
            Class->getSourceRange(), 
            Satisfaction
        );

        if (IsSatisfied) {
            llvm::outs() << "The class " << Class->getName() << " satisfies the concept " << Concept->getName() << ".\n";
        } else {
            llvm::outs() << "The class " << Class->getName() << " does NOT satisfy the concept " << Concept->getName() << ".\n";
        }
    } else {
        llvm::outs() << "The concept " << Concept->getNameAsString() 
                     << " does not have a valid requires expression.\n";
    }
}
最小复现示例
template<typename T>
concept HasFoo = requires(T t) {
    t.foo();
    typename T::Bar;
};

struct GoodClass {
    void foo() {}
    using Bar = int;
};

struct BadClass {
    // 缺少foo()成员函数和Bar类型别名
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 01:16:08