如何通过扩展以下类型特征来删除 decltype(& MyClass::func) 部分?

How to remove decltype(&MyClass::funct) part by extending the following type traits?

我想要类型特征,这将帮助我获得 class 的类型 来自成员函数指针。我调查了 并找到了我的目标。

看起来像这样:

#include <iostream>

// example class
struct MyClass {
    void funct() { std::cout << "funct has been called....\n"; }
};

// traits
template<typename Class> struct get_class{};
template<typename ReType, typename Class, typename... Args>
struct get_class<ReType(Class::*)(Args...)>
{
    using type = Class;
};
template<typename Type> using get_class_t = typename get_class<Type>::type;

int main()
{
    get_class_t<decltype(&MyClass::funct)> myObj;
    //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---> this is a lot of typing
    myObj.funct();
    return 0;
}

但是,如图所示的代码我需要每次都写get_class_t<decltype(&MyClass::funct)> 或者在

的情况下
  auto ptr =  &MyClass::funct;
  get_class_t<decltype(ptr)> myObj;
  //         ^^^^^^^^^^^^^^

很多 decltype()ing。我想改写

class_t<ptr> obj;
or
class_t<&MyClass::funct> myObj;

哪个更方便

我执行了以下函数,它将 return class 的结果对象 也许我可以做,我想做。

template<typename Type>
auto helper_function(Type ptr)->get_class_t<Type>
{
    return get_class_t<Type>{};
}

template<typename Type>
using class_t = /* decltype(helper_function(Type ptr));*/ 
//             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ // what could be here?

我不知道如何完成这个。我的目标是以这样一种方式扩展特征 可以创建一个像

这样的对象
auto ptr = &MyClass::funct;
class_t<ptr> myObj;
// or
class_t<&MyClass::funct> myObj;

还有其他方法吗?还是我必须坚持 decltype()ing?

正如我标记的那样,我想看看 C++11 是否可行?

(为未来的访问者存档答案;此解决方案需要 C++17!)


你真的很接近!

诀窍是 auto 模板参数,事实上 pointers-to-members 可以用作模板参数,如下所示:

template <auto thing>
using class_t = get_class_t<decltype(thing)>;

int main()
{
    class_t<&MyClass::funct> myObj;
    myObj.funct();
}

当然,如果你会写这个,那么你已经知道类型了,所以你只写MyClass,所以这不是很有用。

遗憾的是,您无法让它接受 ptr 作为模板参数;你为此坚持 get_class_t:

int main()
{
    auto ptr = &MyClass::funct;
    get_class_t<decltype(ptr)> myObj;
    myObj.funct();
}

(live demo)

在后一种情况下,一个好的类型别名可以帮助你一点:

auto ptr = &MyClass::funct;

using ClassType = get_class_t<decltype(ptr)>;
ClassType myObj;

myObj.funct();

(live demo)

我个人认为这种冗长程度非常合理。

您可以提供一个函数来创建所需的对象。这个实现起来很简单:

template<typename T, typename ...Args>
auto makeObjectForMethod(T&&, Args&& ...args) -> get_class_t<decltype(&MyClass::funct)>
{
    using R = get_class_t<decltype(&MyClass::funct)>;
    return R{ std::forward(args)... };
}

int main()
{
    auto myObj = makeObjectForMethod(&MyClass::funct);

    myObj.funct();
    return 0;
}

适用于 C++11,非常方便: https://wandbox.org/permlink/usMa3fA0I2HCNJ7M

唯一的缺点是在 class 字段的情况下它不是很有帮助。