【问题标题】:Weird pointer to member function syntax指向成员函数语法的奇怪指针
【发布时间】:2016-01-27 17:12:39
【问题描述】:

我了解如何声明函数的类型:

typedef void (typedef_void_f)(); // typedef_void_f is void()
using alias_void_f     = void(); // alias_void_f is void()

并且可以用来声明函数指针:

void function() { std::cout << __PRETTY_FUNCTION__ << '\n'; }

typedef_void_f *a = function; // pointer to void()
alias_void_f   *b = function; // pointer to void()

对于成员函数指针,语法稍微复杂一些:

struct S { void function() { std::cout << __PRETTY_FUNCTION__ << '\n'; } };

typedef void (S::*typedef_void_m_f)();
using  alias_void_m_f = void (S::*)();

typedef_void_m_f c = &S::function; // pointer to S void() member function
alias_void_m_f   d = &S::function; // pointer to S void() member function

这是我对C++中函数指针的理解,我觉得就够了。

但是在p0172r0 technical paper我发现了一个我不熟悉的语法:

struct host {
   int function() const;
};

template <typename TYPE>
constexpr bool test(TYPE host::*) { // <---- What is this??
    return is_same_v<TYPE, int() const>;
}

constexpr auto member = &host::function;

test(member);

据我了解代码,test 函数 将函数的类型从函数所属的对象的类型中拆分出来,因此在模板 test 函数中 TYPE模板参数将是 void() 但如果我尝试以下操作:

void my_test(void() S::*) {}

my_test(&S::function);

我收到一堆语法错误:

error: variable or field 'my_test' declared void
 void my_test(void() S::*) {}
                   ^
error: expected ')' before 'S'
 void my_test(void() S::*) {}
                     ^
error: 'my_test' was not declared in this scope
     my_test(&S::function);

很明显,我不理解 p0172r0 的 test 函数语法。

谁能解释template &lt;typename TYPE&gt; constexpr bool test(TYPE host::*)语法的细节?

【问题讨论】:

  • 不,我不是在问T::* 在模板参数中的含义。
  • 很抱歉。没有得到它很快重新打开。
  • 这不仅限于成员指针。如果你有using T = int(),那么T* p 是有效的,而int()* p 是语法规则禁止的。
  • @cpplearner 是的,正如我在谈论的p0172r0 paper 中已经指出的那样。

标签: c++ function-pointers member-function-pointers


【解决方案1】:

TYPE host::* 是指向类数据成员的指针。 TYPE 是类成员的类型,host::* 表示指向 host 成员的指针。所以TYPE host::* 接受一个指向host 的任何成员的指针

【讨论】:

  • 那么为什么void my_test(void() S::*) 不接受指向S 的任何void() 成员的指针?
  • @PaperBirdMaster 据了解,指向类数据成员的指针和指向类成员函数的指针指向不同的事物。我从未见过你试图在我见过的任何代码中使用的语法。
  • @PaperBirdMaster 我一直在测试,但我认为 C++ 不允许这样做。见:coliru.stacked-crooked.com/a/5db4e74c2be52aaf
  • 我用 gcc 6.0.0 测试了Wandboxp0172r0 的代码。
  • @PaperBirdMaster 这很有趣。稍后我将不得不深入研究它。
【解决方案2】:

试试这个:

constexpr void my_test(void (S::*)()) {}

这是声明一个指向S的成员函数的参数类型指针的正确方法,返回void而不带参数。

http://ideone.com/EqfYmb

【讨论】:

  • 所以如果my_test(void (S::*)()) 是声明指向void() 成员S 的指针的正确方法,那么template &lt;typename TYPE&gt; constexpr bool test(TYPE host::*) 不应该是template &lt;typename TYPE&gt; constexpr bool test(TYPE (host::*)()) 吗?我不明白p0172r0 的语法。
  • @PaperBirdMaster 我认为可以像你说的那样“拆分”类型,因为模板扣除规则。
猜你喜欢
  • 2016-12-27
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多