无法在clang Linux中分配非静态成员函数,但我可以在Visual Studio Windows中分配

Cannot assign a non-static member function in clang Linux, but I can in Visual Studio Windows?

本文关键字:分配 我可以 Visual Windows Studio clang Linux 静态成员 函数      更新时间:2023-10-16

我有一个非常简单的类,它返回一个字符串:

class Foo
{
public:
const char *GetString() const
{
return "bar";
}
};

我有一个非常简单的类,它包含一个指向GetString的函数指针。

template < class classname >
struct ClassFunctionPointer
{
typedef const char * ( classname::* StringReturner )( void ) const;
StringReturner  stringReturnerFnPtr;
};

然后我有了这段代码,它在Windows(Visual Studio(下编译得很好,但在Linux(clang(下编译不好。

ClassFunctionPointer< Foo > fptrs;
fptrs.stringReturnerFnPtr = &(Foo::GetString);

Linux下的错误为:error: call to non-static member function without an object argument。我不理解这个错误,因为我没有进行函数调用。我只是把函数的地址分配给一个函数指针。

如果我演一个演员也不行:

ClassFunctionPointer< Foo > fptrs;
fptrs.stringReturnerFnPtr = reinterpret_cast< typename ClassFunctionPointer< Foo >::StringReturner >(&(Foo::GetString));

这可以归结为使用括号。让我们生成一个最小的测试用例:

struct Foo
{
int bar();
};
int main()
{
&(Foo::bar);
}

您已表示Visual Studio接受此操作。不应该!

[expr.unary.op/4]:只有当使用显式&并且其操作数是不包含在括号中的限定id时,才形成指向成员的指针[注意:也就是说,表达式&(qualified-id)(限定id括在括号中(不构成"指针到成员"类型的表达式。qualified-id也不构成,因为没有从非静态成员函数的合格id隐式转换为"指针到会员函数"类型正如从函数类型的左值到类型"指向函数的指针"([conv.func](一样。&unqualified-id也不是指向成员的指针,即使在非限定id的类的范围内也是如此--尾注]

我不知道为什么存在这个规则。

无论如何,我尝试过的GCC的每个版本都会拒绝代码:

错误:无效使用非静态成员函数'int Foo::bar(('

这是一种常见的诊断,表示您忘记了&()。某些编译器的某些版本使用了不同的、更令人困惑的措辞("在没有对象参数的情况下调用非静态成员函数"(

Clang对此表示赞同。

Visual Studio对这类事情过于宽容是很常见的。

既然你希望你的代码是可移植的和符合标准的,那就使用更常见的:

&Foo::GetString

也就是说,删除括号