Bug in C++20 concepts with template member functions and std::invocable(模板成员函数和std::Invoocable的C++20概念中存在错误)
问题描述
我正在试验C++20概念和Eigen library,我遇到了意外的行为。具体地说,请考虑以下概念,该概念要求类型可以通过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上编译代码,都得到了这些结果。感谢您能提供的任何帮助!
附注:行
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
,也会满足char
。这看起来与两种特征类型的可转换性有关--请参阅P.S.
如何在不允许隐式转换的情况下表达所需的约束?即FooConcept
必须只允许重载operator()
至少两次,一次重载Eigen::Matrix<double, -1, 1>
,一次重载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:我设法回答了this post中问题的一半。但是,我仍然对从编译器收到的错误消息感到好奇。
推荐答案
is_convertable
只是确定过载是否存在并且可以明确地找到。在Eigen的情况下,存在这些类型之间的重载转换,但主体具有static_assert
。
is_convertable
在说转换操作有效之前,不会实例化转换操作体。这是有意的,以允许C++重载解析不需要编译大量代码。
要使您的特征起作用,需要重新设置Eigen以支持&Quot;SFINAE&Quot;友好的方法和转换操作符。
测试中的失败是因为char矩阵转换为两者,这是不明确的,因此特征失败。这不是您认为它失败的原因。
添加template<class T>
表示不考虑重载(无法推导T),因此明确选择转换为浮点数组。
这篇关于模板成员函数和std::Invoocable的C++20概念中存在错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:模板成员函数和std::Invoocable的C++20概念中存在错误
- XML Schema 到 C++ 类 2022-01-01
- 使用 __stdcall & 调用 DLLVS2013 中的 GetProcAddress() 2021-01-01
- 将函数的返回值分配给引用 C++? 2022-01-01
- 从父 CMakeLists.txt 覆盖 CMake 中的默认选项(...)值 2021-01-01
- 如何提取 __VA_ARGS__? 2022-01-01
- 哪个更快:if (bool) 或 if(int)? 2022-01-01
- OpenGL 对象的 RAII 包装器 2021-01-01
- DoEvents 等效于 C++? 2021-01-01
- 将 hdc 内容复制到位图 2022-09-04
- GDB 不显示函数名 2022-01-01