C++ 概念可以限制类型成员变量吗?

C++ 概念可以限制类型成员变量吗?,c++,c++20,c++-concepts,C++,C++20,C++ Concepts,我使用的是C++20&我想知道概念是否有可能解决这样的情况 假设我有一个函数: 模板 无效剂量测定法(F){ f(); } doSomething接受一个可调用的对象(从技术上讲是lambdas,但我认为不重要)&我想确保F的成员变量没有类型t。例如,我想要: badt型; int x=。。。; 双y=。。。; 剂量测定法([t=kj::mv(t),x,y]{…});//我想要一个编译错误 doSomething([x,y]{…});//没有错误。 类似地,我希望以类似的方式验证可调用的参数

我使用的是C++20&我想知道概念是否有可能解决这样的情况

假设我有一个函数:

模板
无效剂量测定法(F){
f();
}

doSomething
接受一个可调用的对象(从技术上讲是lambdas,但我认为不重要)&我想确保
F
的成员变量没有类型
t
。例如,我想要:

badt型;
int x=。。。;
双y=。。。;
剂量测定法([t=kj::mv(t),x,y]{…});//我想要一个编译错误
doSomething([x,y]{…});//没有错误。
类似地,我希望以类似的方式验证可调用的参数:

doSomething([x,y](BadType t){…});//我想要一个编译错误
doSomething([x,y](标准::向量c){…});//没有编译错误
我不知道这是否会使事情复杂化,但从技术上讲,
BadType
本身就是一种模板类型(我想禁用所有实例,而不管模板值如何)

一个可以接受的答案可能是提供一个例子,但我也很高兴有人认为我应该能够拼凑起来完成的好教程。我对C++和模板元编程非常有经验,但概念目前感觉就像是一个完全陌生的东西。当然,如果这是不可能的,那么我也很乐意接受这样的答案

这感觉像是反射TS非常适合的东西,但即使在v13中,alas clang也没有以一种可访问的方式实现这一点(我认为GCC的工作仍然在非主线分支中)。我已经研究了C++17的各种静态反射库,但是它们都需要修改类型,这在这里是不可能的,因为我正在内省lambda(而
BadType
是在3p库中定义的类型,尽管这不重要)


我猜答案一定是否定的,因为我传入的每个lambda都会有一组任意的变量名称,这些变量都是被捕获的&我见过的唯一一个尝试强制成员变量类型的概念示例需要一个已知的变量名称,但对于概念大师来说,这可能是一个有趣的挑战。

您可以使用以下方法轻松检查一个简单的
结构
/aggregate
T
是否包含任何类型为
TType
的字段:


如果您只喜欢检查简单结构/聚合中对象的直接嵌套,请参阅

如果您的目标是禁止在可调用对象内捕获某种类型的对象(例如,禁止在异步回调中捕获引用或禁止捕获不应从回调中访问的对象),那么在一般情况下,即使使用反射TS,也不可能

简单的反例:

BadType t;
doSomething([t = std::any(kj::mv(t))]{...}); // Even reflection TS could not do anything with this.
另一个:

struct Fun {
    std::any v;
    void operator()() {
       ....
    }
}

Fun f = ...
doSomething(std::move(f)); // Event more powerful reflection than reflection TS (reflection with statements reflection) could not do anything with this.

即使可以考虑任何类型的擦除也不能。

“确保F的任何成员变量都没有类型T”这是完全不可能的。“验证可调用函数的参数”不太清楚要验证什么。您正在调用没有参数的callable,因此接受任何参数的callable将导致编译错误。请阅读以下内容,了解为何转发函子:@n.“代词m:”“确保F的任何成员变量都没有类型T”这是完全不可能的。错。看看我的答案。你为什么要这个?我很难找到这样做的理由。@VittorioRomeo lambda不是一个简单的结构,也不是一个聚合。这是一个非常简洁和有用的链接。不幸的是,我需要一个lambdas的解决方案。在这种情况下,自定义可调用将不起作用(大型代码库,因此手动转换将非常耗时,除非我缺少某种方法来实现)。我不相信有任何方法可以在C++20中模拟lambda捕获的反射。当然,在我所拥有的用例中,我没有需要担心的类型擦除实例,因此这是一个极端的反例(即,如果反射TS可用,它应该可以工作)。这只是一个中间地带,我没有简单的结构/聚合&我需要在lambda上实施这一点,该lambda具有我想要实施的已知当前模式。也许semgrep会是一个很好的中间地带。
struct my_callable
{
    float f;
    float operator()() { return f; }
};

void f0(having_any_data_member_of_type<float> auto f)
{
    (void) f();
}

int main()
{
    f0(my_callable{}); // OK
}
BadType t;
doSomething([t = std::any(kj::mv(t))]{...}); // Even reflection TS could not do anything with this.
struct Fun {
    std::any v;
    void operator()() {
       ....
    }
}

Fun f = ...
doSomething(std::move(f)); // Event more powerful reflection than reflection TS (reflection with statements reflection) could not do anything with this.