【问题标题】:How do you get the type of a member function如何获取成员函数的类型
【发布时间】:2018-05-07 10:29:48
【问题描述】:

这个问题的灵感来自标准[class.mem]中的注释

非静态成员函数的类型是普通函数类型,非静态数据成员的类型是普通对象类型。没有特殊的成员函数类型或数据成员类型。

所以,我决定测试一下

struct S
{
    using Fn = void();
    Fn foo;

    static_assert(std::is_same_v<decltype(foo), Fn>);
};

但在decltype(foo) 出现错误:非静态成员函数的使用无效。

如何获取成员函数的类型?还是那张纸条是假的?

注意:对数据成员这样做是有效的

struct U
{
    int i;
    static_assert(std::is_same_v<decltype(i), int>);
};

注意2:我不是在寻找如何通过指向成员的指针来获取类型

template<typename>
struct NotLikeThis;
template<typename C, typename R, typename... Args>
struct NotLikeThis<R (C::*)(Args...)>
{
    using type = R(Args...);
};

标准中的注释与此无关。

【问题讨论】:

  • 你只是没有,看起来。相关:stackoverflow.com/questions/47263793/…
  • 如果我们不能decltype member_function,我想知道这个注释的目的是什么。
  • @geza 正是我的想法
  • @StoryTeller 我记得。我想知道是否有可能获得该类型。
  • 您可以使用static_assert(std::is_same_v&lt;decltype(&amp;S::foo), Fn S::*&gt;); 来检查非静态成员的类型,但我不确定这是否是您的问题。

标签: c++ language-lawyer


【解决方案1】:

标准明确规定您不能这样做。

[expr.prim.id]

2 id-expression 表示类的非静态数据成员或非静态成员函数只能使用:

   (2.1) 作为class member access 的一部分,其中对象表达式引用成员的类58 或从该类派生的类,或

   (2.2) 形成指向成员 ([expr.unary.op]) 的指针,或

   (2.3) 如果 id-expression 表示一个非静态数据成员并且它出现在未计算的操作数中。

[ 示例:

struct S {
  int m;
};
int i = sizeof(S::m);           // OK
int j = sizeof(S::m + 42);      // OK

——结束示例 ]

注意我对只能使用的强调:这些是您可以使用表示成员函数的表达式的唯一方法。你能想出的任何其他方法都是错误的。

请注意,2.3 正是您想要的 - 在未评估的上下文(即:decltype)中使用 S::m(m 是一个成员函数),但它特别(我会假设 deliberately) 仅适用于 data 成员。

我可以想到至少允许这样做的一个含义(见下文)。可能还有更多。

  • 假设m 被声明为void m();,它是S 类的成员。如果decltype(S::m) 有效,那么std::add_pointer&lt;decltype(S::m)&gt; 也应该有效。
    考虑到成员函数具有隐式this 参数, 第二种类型是什么? void (S::*)(),或者什么 喜欢void (*)(S*)?甚至void (*)()?对我们来说,我们想要void (S::*)() 可能很明显,但是知道S::m 只是一个常规函数类型,为什么add_pointer 会将它变成指向成员的指针?它怎么能区分它?

【讨论】:

    猜你喜欢
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    相关资源
    最近更新 更多