void(U :: *)(void)是什么意思?

我正在研究Boost中
is_class
模板的实现,并遇到了一些我无法轻易解读的语法。
    template <class U> static ::boost::type_traits::yes_type is_class_tester(void(U::*)(void));
    template <class U> static ::boost::type_traits::no_type is_class_tester(...);
我如何理解上面的
void(U::*)(void)
?我熟悉C,所以看起来有点类似于
void(*)(void)
,但我不明白
U::
如何修改指针。有人可以帮忙吗? 谢谢     
已邀请:
*
表示指针,因为您可以通过写
*p
来访问其内容。
U::*
表示指向类
U
成员的指针。您可以通过写
u.*p
pu->*p
(其中
u
U
的实例)来访问其内容。 所以,在你的例子中,
void (U::*)(void)
是一个指向
U
成员的指针,它是一个不带参数且不返回任何值的函数。 例:
class C { void foo() {} };

typedef void (C::*c_func_ptr)(void);

c_func_ptr myPointer = &C::foo;
    
你是对的,它类似于一个函数指针。相反,这是一个指向成员函数的指针,其中成员属于类
U
。 类型的差异是必要的,因为成员函数具有隐式的
this
指针,因为它们不能在没有实例的情况下调用。摆脱模板可能会使它更容易:
struct foo
{
    void bar(void);
};
void(*)(void)
不会这样做,因为这无法传达班级的实例。相反,我们需要:
void (foo::*)(void)
指示此函数指针需要一个实例
foo
。 对于它的价值,你可以像这样使用它们:
typedef void (foo::*func_ptr)(void);

foo f;
foo* fp = &f;
func_ptr func = &foo::bar;

(f.*func)();
(fp->*func)();
    
它是指向U类成员函数的指针。 它非常相似 无效(*)(无效) 但它指向U类的成员函数。     
从U开始,然后在里面工作。 声明的类型是一个指向U类成员函数的指针,它接受void参数并返回void。     
我打算问这个同样的问题,但已经有人问了。不幸的是,现有的答案都没有真正回答这个问题。至少不适合我。我不得不把它拼出来。我想提出与OP相同的问题,加上一些问题。我的问题:WTF是这个
is_class_tester (void (U::*)(void))
的东西,这个结构如何在SFINAE(替换失败不是错误)的背景下工作? 通过一些简化,Boost使用如下构造:
template <typename U>
char is_class_tester (void (U::*)(void));

template <typename U>
TypeBiggerThanChar is_class_tester (...);

template <typename T>
struct IsClass {
   static const bool value = sizeof (is_class_tester<T>(0)) == 1;
};
一些观察: 那些功能模板实际上不是功能模板。它们只是一对重载函数模板的前向声明。从不定义函数模板本身。看到这是如此并且理解其如何工作而不需要定义模板是理解该构造的关键元素之一。 谈到如何使用这个第一个功能模板的答案错过了船。您不能使用此功能模板,因为它的定义不存在。 请注意,由于这个神秘的参数,只有当类型
T
是一个类时,两个函数模板中的第一个才有意义。基本类型和指针没有成员函数。第一个声明是非类类型的无效语法。 与第二个重载函数模板形成对比,后者是所有模板参数的有效语法,并且函数(如果存在)将由于其可变参数...参数而将任何参数抛出。 (旁白:这模糊地让人联想到我最喜欢的单行C程序,它可以解决世界上任何问题,给出正确格式化的用户输入。) 虽然函数模板声明不能用作函数,但声明可用于简单的编译时查询,例如关于返回类型的查询。这种查询不需要实际定义。只需要原型。 这正是类模板
IsClass
定义编译时常量
IsClass<SomeType>::value
的作用。 那么
IsClass<SomeType>::value
如何获得它的价值,它在编译时是如何做到的?编译器必须要理解
sizeof (is_class_tester<T>(0))
或放弃尝试。我们需要根据类型
SomeType
是否是类来查看两个案例。 案例1:
SomeType
是一个班级。 这里两个模板声明都是有效的语法,因此编译器有两个可供选择的候选者。编译器可以而且必须是第一个函数模板,因为选择规则规定可变参数函数在选择中获得最低优先级。此选定函数返回一个char。由于sizeof(char)保证为1,因此在
SomeType
为类时,
IsClass<SomeType>::value
为真。 案例2:
SomeType
不是一个班级。 这是SFINAE开始的地方。第一个函数模板声明是无效的语法。由于SFINAE,编译器不能只放弃这里。它必须继续寻找替代方案,第二个功能模板声明符合要求。唯一可行的函数返回
TypeBiggerThanChar
,定义省略,但希望很明显。我们想要的只是sizeof()这个东西。它比一个字符大,所以如果
SomeType
不是一个类,
IsClass<SomeType>::value
将是假的。     

要回复问题请先登录注册