【问题标题】:Declaring pointer to method with decltype in C++在 C++ 中使用 decltype 声明指向方法的指针
【发布时间】:2017-04-02 03:43:07
【问题描述】:

clanggcc 之间存在一些差异。其中之一是他们如何处理指向方法的指针。给定以下代码:

template <typename T_Class, typename T_Ret, typename ... Args>
void store_method(T_Class *object, T_Ret (T_Class::*method)(Args ... args));

class SomeObjectWithPotentiallyLongName {
     int commonly_used_method(int var);
     void register_method() {
          /* The code below is okay for gcc with -std=gnu++11. But clang
           * says:
           * 'reference to non-static member function must be called' */
          store_method(this, commonly_used_method);
          /* To make this fine for clang (and also - gcc), I have to 
           * extend previous line as next */
          store_method(this, &SomeObjectWithPotentiallyLongName::commonly_used_method);
     }
}

上面的代码显示了在许多地方扩展代码以使其可以被clang编译的必要性,而它可以像gcc一样简洁明了。

最明显的方法是编写一些宏,将thismethod_name 变成&amp;TypeOfThis::method_name 之类的东西。

我的想法是使用decltype:

#define STORE_METHOD(method) store_method(this, (decltype(*this))::method)

void SomeObjectWithPotentiallyLongName::register_method() {
     STORE_METHOD(commonly_used_method);
}

但是这段代码会产生以下clang 的错误:

“decltype(*this)”(又名“SomeObjectWithPotentiallyLongName &”)不是类、命名空间或枚举

有没有办法构建这样的宏?如果没有,有没有其他方法可以解决这个问题?

【问题讨论】:

    标签: c++ pointers gcc methods clang


    【解决方案1】:

    T &amp; 不是在这种情况下可用的类型(正如在 cmets 中指出的那样,它仍然是一种类型),它是一个引用。您可以使用std::remove_reference&lt;...&gt;::type (documentation) 来删除引用并改为获取T 类型:

    typedef std::remove_reference<decltype(*this)>::type T;
    

    然后使用:

    T::method
    

    【讨论】:

    • T&amp; 是一种类型。它可能不是你想要的类型,但它是一种类型。
    【解决方案2】:

    您在宏中错过了&amp;。此外decltype 可能会产生一个合格的引用类型,所以你应该使用std::decay 来删除引用和限定符:

    #define STORE_METHOD(method)\
        store_method(\
            this,\
            &std::decay<decltype(*this)>::type::method\
        )
    

    或 C++14 中的 std::decay_t

    #define STORE_METHOD(method)\
        store_method(\
            this,\
            &std::decay_t<decltype(*this)>::method\
        )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-20
      • 1970-01-01
      • 2010-09-18
      • 2022-08-16
      相关资源
      最近更新 更多