C++ C+中的Bug+;具有模板成员函数和std::invocable的20个概念

C++ C+中的Bug+;具有模板成员函数和std::invocable的20个概念,c++,eigen,c++20,concept,invocable,C++,Eigen,C++20,Concept,Invocable,我在试验C++20的概念和方法,结果出现了一个意想不到的行为。具体来说,考虑下面的概念,要求一个类型可以用一个 EGEN::矩阵> 对象或特征::矩阵> : template <class FOO_CONCEPT> concept FooConcept = std::invocable<FOO_CONCEPT, Eigen::Matrix<double, -1, 1>> && std::invocable<FOO_CONCEPT,

我在试验C++20的概念和方法,结果出现了一个意想不到的行为。具体来说,考虑下面的概念,要求一个类型可以用一个<代码> EGEN::矩阵> <代码>对象或<代码>特征::矩阵> <代码>:
template <class FOO_CONCEPT>
concept FooConcept = std::invocable<FOO_CONCEPT, Eigen::Matrix<double, -1, 1>> &&
    std::invocable<FOO_CONCEPT, Eigen::Matrix<char, -1, 1>>;
打印
0
。但是,当我切换行注释(*)时,即当
操作符()
是一个模板时,相同的代码会奇怪地打印
1
。这是虫子吗?我使用clang12.0.1和gcc11.1.0在visualstudio代码上编译代码,得到了这些结果。谢谢你能提供的任何帮助

附言:电话线

 std::cout << std::is_convertible<Eigen::Matrix<char, -1, 1>, Eigen::Matrix<float, -1, 1>>()
              << std::endl;
FooImplicit
结构实际上满足了
FooConcept
,如果将
char
替换为
double
,也会发生同样的情况。这看起来与两种本征类型的可兑换性有关——见P.S

如何在不允许隐式转换的情况下表达我想要的约束?也就是说,
FooConcept
必须只允许重载
操作符()
的类至少两次,一次使用
Eigen::Matrix
,一次使用
Eigen::Matrix
。这能做到吗

另外,如果我定义函数

void func(FooConcept auto x) {}
我试着把它叫做
func(Foo())保留行(*)注释,我得到以下编译错误:

[build] [...]: note: because 'Foo' does not satisfy 'FooConcept'
[build] void func(FooConcept auto x) {
[build]               ^
[build] [...]: note: because 'std::invocable<Foo, Eigen::Matrix<char, -1, 1> >' evaluated to false
[build][…]:注意:因为“Foo”不满足“FooConcept”
[build]无效函数(FooConcept auto x){
[建造]^
[生成][…]:注意:因为“std::invocable”的计算结果为false
这是因为编译器无法明确选择调用哪个重载?如果是,为什么错误消息不更明确?在我看来,编译器似乎注意到
Foo
有两个成员函数,一个是正确的,而另一个不是



编辑2:我在中成功地回答了一半的问题。但是,我仍然对从编译器中得到的错误消息感到好奇。

是可转换的。
仅确定重载是否存在并且可以毫不含糊地找到。在Eigen的情况下,这些类型之间的重载转换存在,但主体有一个
静态断言


<代码> ISHOLTAULTABLE 不在转换操作之前实例化转换操作的主体。这是有意的,允许C++重载解决方案不需要编译大量代码。

为了让您的traits发挥作用,需要重新连接Eigen以支持“SFINAE”——友好的方法和转换操作符

测试中的失败是因为字符矩阵转换为二者,这是不明确的,所以这个特征失败了。这不是你认为它失败的原因


添加
模板
意味着不考虑重载(无法推导t),因此明确选择转换为浮点数组。

“打印1,但不能隐式地将Eigen::Matrix对象转换为Eigen::Matrix。”是什么让你这么肯定?C++似乎认为它是正确的,而且它通常是正确的。我亲自测试了它;EGEN使你在不同的矩阵类型之间明确地铸造!<代码> STD::ISSULTIONEX/CODEN>报告>代码>真/ <代码> -但是<代码> EGEG<代码>有一个<代码> StistaSysAt> <代码>阻止转换,所以
Eigen
在这个意义上并不友好。我想我理解了你答案的第一部分,这似乎是合理的,所以谢谢!“你测试的失败是因为字符矩阵转换为二者,这是不明确的,所以特征失败。这不是你认为失败的原因。”我不确定这句话,请参考主要问题中的编辑。“添加模板意味着不考虑重载(不能推断t),因此明确选择转换为浮点数组。”如果前面的语句是正确的,则此语句看起来是正确的。请再次参考主问题中的编辑!作为后续注释,当我添加
模板
和模板专用化
模板无效运算符()(Eigen::Matrix){}
,我仍然认为
Foo
满足了
FooConcept
,这是我不期望的。在这种情况下,编译器的重载选择也应该是不明确的,不是吗?@fdev我很确定模板专门化在重载解析中不起作用。因此,添加一个不会有什么不同你能详细说明一下吗?谢谢!好吧,我想你指的是这个。很好!
struct FooImplicit {
    void operator()(Eigen::Matrix<char, -1, 1>) {
    }
};
void func(FooConcept auto x) {}
[build] [...]: note: because 'Foo' does not satisfy 'FooConcept'
[build] void func(FooConcept auto x) {
[build]               ^
[build] [...]: note: because 'std::invocable<Foo, Eigen::Matrix<char, -1, 1> >' evaluated to false