在C++中使用decltype声明方法指针

4

clang和gcc之间有一些差异。其中一个差异是它们如何处理指向方法的指针。给定以下代码:

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转换为类似于&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 &')不是类、命名空间或枚举

有没有办法构建这样的宏?如果没有,是否有其他解决方案?

2个回答

4

好的,T & 不是在此上下文中可用的类型(正如评论中指出的那样,它仍然是一种类型),而是一个引用。您可以使用 std::remove_reference<...> ::type (文档) 来去除引用并获得 T 类型:

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

然后使用:

T::method

1
T& 是一种类型。它可能不是你想要的类型,但它确实是一种类型。 - Nir Friedman

3

您的宏中缺少&。此外,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\
    )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接