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

C++ Concepts:requires子句为何未检测构造函数内部约束?

C++ Concepts中requires子句的判断矛盾问题探究

问题背景

通过最小可复现示例(MWE)探究C++ Concept里requires子句的特殊现象,目标是实现一个判断函数类型能否被指定参数调用的concept(尽管std::invocable可实现该功能,此处仅作演示)。

定义的concept如下:

template <typename func_t, typename... args_t>
concept callable = requires(const func_t& f, const args_t&... args) {f(args...);};

按预期,只要调用操作合法(包含隐式类型转换),该concept应返回true。例如用接受const double&的lambda测试时,callable<decltype(func), int>和callable<decltype(func), double>均为true,符合预期。

自定义类型测试与矛盾现象

首先定义一组自定义类型:

enum space {space1,space2};

template <const space sp> struct type2_t{};

template <const space sp> struct type1_t
{
    type1_t(){}

    template <const space sp_r>
    type1_t(const type2_t<sp_r>& t2){}
};

此时type2_t可任意转换为type1_t,对应的三个callable判断均为true,符合预期。若在type1_t的构造函数上添加requires (sp_r == sp)约束,callable<decltype(func), type2_t<space2>>会变为false,也符合预期。

但当移除构造函数的requires约束,转而在构造函数内部调用的dummy_func上添加该约束时:

template <const space sp> struct type1_t
{
    type1_t(){}

    template <const space sp_r>
    requires (sp_r == sp)
    void dummy_func(const type2_t<sp_r>& t2){}

    template <const space sp_r>
    type1_t(const type2_t<sp_r>& t2)
    {
        dummy_func(t2);
    }
};

预期callable<decltype(func), type2_t<space2>>应为false,但实际结果为true。然而直接调用func(type2_t<space2>())会编译失败,这与concept的判断结果产生矛盾。

核心疑问

  • 该矛盾的根源是什么?
  • 为何编译器未完全检查concept的requires子句内代码的有效性?

附录

  • 已知应使用std::invocable,此处仅作演示,且std::invocable存在同样问题。
  • 将约束放在type1_t构造函数上可解决问题,但这在项目中不可行。

完整测试代码

#include <iostream>
#include <concepts>

enum space
{
    space1,
    space2
};

template <typename func_t, typename... args_t>
concept callable = requires(const func_t& f, const args_t&... args) {f(args...);};

template <const space sp> struct type2_t{};

template <const space sp> struct type1_t
{
    type1_t(){}

    template <const space sp_r>
    requires (sp_r == sp)
    void dummy_func(const type2_t<sp_r>& t2){}

    template <const space sp_r>
    type1_t(const type2_t<sp_r>& t2)
    {
        dummy_func(t2);
    }
};

int main(int argc, char** argv)
{
    auto func = [](const type1_t<space1>& t1) -> int {return 1;};
    std::cout << callable<decltype(func), type1_t<space1>> << std::endl; //true
    std::cout << callable<decltype(func), type2_t<space1>> << std::endl; //true
    std::cout << callable<decltype(func), type2_t<space2>> << std::endl; //true, should be false!!
}

注:使用g++ 11.3,编译参数-std=c++20。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 06:45:52