我正在尝试使用 C++20 概念和Eigen 库,但发生了意外行为。具体来说,考虑以下概念,要求类型可以用Eigen::Matrix<double, -1, 1>>
对象或对象调用Eigen::Matrix<char, -1, 1>>
:
template <class FOO_CONCEPT>
concept FooConcept = std::invocable<FOO_CONCEPT, Eigen::Matrix<double, -1, 1>> &&
std::invocable<FOO_CONCEPT, Eigen::Matrix<char, -1, 1>>;
然后,查看以下结构中的注释行 (*):
struct Foo {
// template <typename T> <---- (*)
void operator()(Eigen::Matrix<double, -1, 1>) {
}
void operator()(Eigen::Matrix<float, -1, 1>) {
}
};
请注意,该类Foo
不满足 的要求,FooConcept
因为它不能用Eigen::Matrix<char, -1, 1>
参数调用。的确:
std::cout << FooConcept<Foo> << std::endl;
打印0
。但是,当我切换行注释 (*) 时,即当operator()
是模板时,相同的代码会奇怪地打印1
. 这是一个错误吗?我使用 Clang 12.0.1 和 GCC 11.1.0 在 Visual Studio Code 上编译代码时得到了这些结果。感谢您提供任何帮助!
PS:线
std::cout << std::is_convertible<Eigen::Matrix<char, -1, 1>, Eigen::Matrix<float, -1, 1>>()
<< std::endl;
打印1
,但Eigen::Matrix<char, -1, 1>
不能将对象隐式转换为Eigen::Matrix<float, -1, 1>
. 这是另一个错误吗?这是否与上述问题相关?
编辑1:我注意到通过定义
struct FooImplicit {
void operator()(Eigen::Matrix<char, -1, 1>) {
}
};
FooImplicit
结构实际上满足FooConcept
,如果替换为 ,也会发生同样char
的情况double
。这看起来与两种 Eigen 类型的可转换性有关——见 PS
如何在不允许隐式转换的情况下表达我想要的约束?也就是说,FooConcept
必须只允许operator()
至少重载两次的类,一次 withEigen::Matrix<double, -1, 1>
和一次 with Eigen::Matrix<char, -1, 1>
。这可以做到吗?
另外,如果我定义函数
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
这是因为编译器无法明确选择要调用的重载吗?如果是,为什么错误消息不更明确?对我来说,它看起来就像编译器注意到它Foo
有两个成员函数,一个是正确的,而另一个不是。
编辑2:我设法回答了这篇文章中的一半问题。但是,我仍然对我从编译器得到的错误信息感到好奇。