C++ 别名模板中的模板参数推断-typedefing任意成员函数指针

C++ 别名模板中的模板参数推断-typedefing任意成员函数指针,c++,templates,c++11,c++14,template-argument-deduction,C++,Templates,C++11,C++14,Template Argument Deduction,作为一个问题,我建议使用模板别名来定义成员函数的签名;也就是说,不仅仅是类型定义成员函数,而且能够分解出包含该方法的目标类: template<typename T> using memberf_pointer = int (T::*)(int, int); 模板 使用memberf_pointer=int(T::*)(int,int); 虽然这似乎涵盖了问题的内容,但我尝试将其推广到任意函数参数: template<typename T, typename... Arg

作为一个问题,我建议使用模板别名来定义成员函数的签名;也就是说,不仅仅是类型定义成员函数,而且能够分解出包含该方法的目标类:

template<typename T>
using memberf_pointer = int (T::*)(int, int); 
模板
使用memberf_pointer=int(T::*)(int,int);
虽然这似乎涵盖了问题的内容,但我尝试将其推广到任意函数参数:

template<typename T, typename... Args>
using memberf_pointer = int (T::*)(Args&&...); 
模板
使用memberf_pointer=int(T::*)(Args&&;
它因参数推断问题而失败(基本上它假定一个空的arument列表)。这里有一个:

#包括
福班
{
公众:
int g(int x,int y){返回x+y;}
};
模板
使用memberf_pointer=int(T::*)(Args&&;
int main()
{
福福;
memberf_指针mp=&foo::g;

std::cout为什么不在这种情况下简单地使用auto呢?在这种情况下使用模板的唯一优点是能够显式地提供您的类型

另一方面,如果希望模板自动推断函数类型,则需要直接对该类型进行参数化。如果还希望模板为您提供所有构建块,最简单的方法是将其专门化为函数或成员函数。例如:

template<typename T> struct memberf_pointer_descriptor;

template<typename TOwner, typename TRet, typename... Args>
struct memberf_pointer_descriptor<TRet(TOwner::*)(Args...)>
{
    // Your stuff goes here.
    using type = TRet(TOwner::*)(Args...);
};

memberf_pointer_descriptor<decltype(&foo::g)>;
模板结构成员指针描述符;
模板
结构成员指针描述符
{
//你的东西放在这里。
使用type=TRet(TOwner::*)(Args…);
};
memberf\u指针\u描述符;

或者直接将foo::g作为参数的函数模板,以减少使用显式decltype的需要。这取决于您的需要。

使示例正常工作的方法如下:

#include <iostream>

class foo
{
public:
    int g(int x, int y) { return x + y; }
};

template<typename T, typename...Args>
using memberf_pointer = int (T::*)(Args...);

int main()
{
    foo f;
    memberf_pointer<foo, int, int> mp = &foo::g;
    std::cout << (f.*mp) (5, 8) << std::endl;
}
#包括
福班
{
公众:
int g(int x,int y){返回x+y;}
};
模板
使用memberf_pointer=int(T::*)(Args;
int main()
{
福福;
memberf_指针mp=&foo::g;

std::coutC++没有类似于类型推断系统的功能,并且它不适用于特定的右值赋值

memberf_pointer<foo> mp = &foo::g ;
  • 显式提供类型或指针类型

    template<typename T>
    using memberf_pointer = T;
    
    memberf_pointer<decltype(&foo::g)> mp = &foo::g;
    
    模板
    使用memberf_指针=T;
    memberf_指针mp=&foo::g;
    

  • Cfr.

    问题标题和正文中的措辞都具有误导性。在你的例子中,任何地方都没有模板推导。当你写:

    memberf_pointer<foo> mp = &foo::g;
    
    由于
    g
    接受参数的明显原因,它无法编译。在赋值语句中获取模板推断的方法是使用
    auto

    auto mp = &foo::g;
    
    mp
    的类型将与您调用的
    U
    的类型相同:

    template <typename U> void meow(U );
    meow(&foo::g);
    
    这会给你和以前一样的类型

    当然,即使您提供了正确的参数列表:

    memberf_pointer<foo, int, int> mp = &foo::g;
    
    如果我们有一个接受右值引用的成员函数,那么我们可以显式地提供它:

    class bar
    {
    public:
      int h(int&& x, int&& y) { return x + y ; }
    };
    
    memberf_pointer<bar, int&&, int&&> mb = &bar::h;
    
    类栏
    {
    公众:
    inth(int&&x,int&&y){返回x+y;}
    };
    memberf_指针mb=&bar::h;
    
    为什么不简单地使用
    auto
    呢?
    auto-mp=&foo::g;
    应该可以工作。赋值不是成员函数参数的演绎上下文。不过有一些解决方法:和@Nawaz我正在使用命令模式,希望确保我正在将接收器的成员函数传递给命令的构造在这种情况下,拥有一个“有意识的”typedef会很好(另一个选择是构建一个特征系统或使用概念).
    auto
    很好,但在我的情况下不是这样。在这里,您只需为成员函数实现
    identity
    类型。我正在玩命令模式,希望确保我正在将接收器的成员函数传递给命令对象的构造。在这种情况下,“有意识的”typedef会很好(另一种选择是构建特征系统或使用概念)。
    auto
    很棒,但我不是在玩命令模式,我想确保我正在将接收者的成员函数传递给命令对象的构造。在这种情况下,“有意识的”typedef会很好(另一个选择是建立一个特征系统或使用概念)。
    auto
    很好,但在我的情况下不是很好的解决办法。
    memberf\u pointer mp=&foo::g;
    是一个右值赋值吗?@NikosAthanasiou它是一个
    int(foo:*)(int,int)类型的右值
    我可以对
    memberf\u pointer mp=&foo::g
    是一个右值赋值(见马可的回答)发表评论吗?@NikosAthanasiou
    &foo::g
    是一个右值,但这在这里并不相关(如果你有
    自动fg=&foo::g;memberf\u pointer mp=fg
    ,它将是一个“左值赋值”,并且仍然因为完全相同的原因而失败)。主要的一点是,当您显式指定类型时,没有类型推断。
    template <typename U> void meow(U );
    meow(&foo::g);
    
    decltype(&foo::g) mp = &foo::g;
    
    memberf_pointer<foo, int, int> mp = &foo::g;
    
    template<typename T, typename...Args>
    using memberf_pointer = int (T::*)(Args...); 
    
    memberf_pointer<foo, int, int> mp = &foo::g;
    
    class bar
    {
    public:
      int h(int&& x, int&& y) { return x + y ; }
    };
    
    memberf_pointer<bar, int&&, int&&> mb = &bar::h;