SFINAE 检查继承的成员函数
使用 SFINAE,我可以检测 给定的类是否具有特定的成员函数。但是如果我想测试继承的成员函数怎么办?
以下代码在 VC8 和 GCC4 中不起作用(即检测到 A
有一个成员函数 foo()
,但不检测到 B
继承了一个成员函数) :
#include <iostream>
template<typename T, typename Sig>
struct has_foo {
template <typename U, U> struct type_check;
template <typename V> static char (& chk(type_check<Sig, &V::foo>*))[1];
template <typename > static char (& chk(...))[2];
static bool const value = (sizeof(chk<T>(0)) == 1);
};
struct A {
void foo();
};
struct B : A {};
int main()
{
using namespace std;
cout << boolalpha << has_foo<A, void (A::*)()>::value << endl; // true
cout << boolalpha << has_foo<B, void (B::*)()>::value << endl; // false
}
那么,有没有办法测试继承的成员函数呢?
Using SFINAE, i can detect wether a given class has a certain member function. But what if i want to test for inherited member functions?
The following does not work in VC8 and GCC4 (i.e. detects that A
has a member function foo()
, but not that B
inherits one):
#include <iostream>
template<typename T, typename Sig>
struct has_foo {
template <typename U, U> struct type_check;
template <typename V> static char (& chk(type_check<Sig, &V::foo>*))[1];
template <typename > static char (& chk(...))[2];
static bool const value = (sizeof(chk<T>(0)) == 1);
};
struct A {
void foo();
};
struct B : A {};
int main()
{
using namespace std;
cout << boolalpha << has_foo<A, void (A::*)()>::value << endl; // true
cout << boolalpha << has_foo<B, void (B::*)()>::value << endl; // false
}
So, is there a way to test for inherited member functions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
看看这个帖子:
http://lists.boost.org/ boost-users/2009/01/44538.php
源自该讨论中链接的代码:
结果:
Take a look at this thread:
http://lists.boost.org/boost-users/2009/01/44538.php
Derived from the code linked to in that discussion:
Result:
joshperry 的答案非常聪明和优雅,但是(正如帖子下面所述)它没有正确检查 foo() 的签名,并且不适用于基本类型(如 int):它会导致编译器错误。
我将提出一种正确处理继承成员并检查成员函数签名的技术。我不会详细介绍细节,而是给您两个示例,并希望代码能够说明一切。
示例1:
我们正在检查具有以下签名的成员:
T::const_iterator begin() const
请注意,它甚至检查方法的常量性,并且也适用于原始类型。 (我的意思是
has_const_begin::value
为 false,不会导致编译时错误。)示例 2
现在我们正在寻找签名:
void foo(MyClass&, unsigned)
请注意,MyClass 不必是默认可构造的或满足任何特殊概念。该技术也适用于模板成员。
我热切地等待对此的意见。
joshperry's answer is very clever and elegant, but (as it is stated below the post) it doesn't check the signature of foo() properly and doesn't work with fundamental types (like int): it causes a compiler error.
I will propose a technique that handles inherited members correctly and also checks the signature of the member function. Instead of going into details I will give you two exampes and hope that the code will speak for itself.
Example1:
We are checking for a member with the following signature:
T::const_iterator begin() const
Please notice that it even checks the constness of the method, and works with primitive types, as well. (I mean
has_const_begin<int>::value
is false and doesn't cause a compile-time error.)Example 2
Now we are looking for the signature:
void foo(MyClass&, unsigned)
Please notice that MyClass doesn't has to be default constructible or to satisfy any special concept. The technique works with template members, as well.
I am eagerly waiting opinions regarding this.
以下是一些使用片段:
*所有这一切的核心是
检查给定类中的成员
x
。可以是 var、func、class、union 或 enum:检查成员函数
void x()
:检查成员变量
x
:检查成员类
x
:检查成员联合
x
:检查成员枚举
x
:检查任何成员函数
x
,无论签名如何:或
详细信息和核心:
宏(El Diablo!):
CREATE_MEMBER_CHECK:
CREATE_MEMBER_VAR_CHECK:
CREATE_MEMBER_FUNC_SIG_CHECK:
CREATE_MEMBER_CLASS_CHECK:
CREATE_MEMBER_UNION_CHECK
:
CREATE_MEMBER_ENUM_CHECK:
CREATE_MEMBER_FUNC_CHECK: CREATE_MEMBER_CHECKS:
Here are some usage snippets:
*The guts for all this are farther down
Check for member
x
in a given class. Could be var, func, class, union, or enum:Check for member function
void x()
:Check for member variable
x
:Check for member class
x
:Check for member union
x
:Check for member enum
x
:Check for any member function
x
regardless of signature:OR
Details and core:
Macros (El Diablo!):
CREATE_MEMBER_CHECK:
CREATE_MEMBER_VAR_CHECK:
CREATE_MEMBER_FUNC_SIG_CHECK:
CREATE_MEMBER_CLASS_CHECK:
CREATE_MEMBER_UNION_CHECK:
CREATE_MEMBER_ENUM_CHECK:
CREATE_MEMBER_FUNC_CHECK:
CREATE_MEMBER_CHECKS:
由于所有答案对我来说都太复杂,我想使用
std::declval
和std::enable_if
介绍我自己的解决方案(GCC 4.8 .3)注意:这不是对签名的精确检查,而是对具有可转换返回类型的可调用函数的检查。(编辑:从
is_same
到is_convertible
)测试
输出
更新:我的跳棋
测试代码
输出
As all of the answers look too complicated to me, I'd like to introduce my own solution using
std::declval
andstd::enable_if
(GCC 4.8.3)NOTE: It is not precise check for signature, but for callable function with convertible return type. (edit: changed from
is_same
tois_convertible
)Test
Output
UPDATE: My checkers
Test Code
Output