如何 typedef 绑定成员方法,然后将该类型用作模板参数?

How can I typedef a bound a member method and then use that type as a template parameter?

我正在尝试绑定 class 的方法并将其作为模板参数传递给不同的 class。这种类型需要在多个方法中使用,所以我尝试在 class(下面的 struct base)中使用 using 子句。 但是,我真的无法获得正确的类型。这些是(大部分)我到目前为止尝试过的:

#include <functional>
#include <utility>
#include <type_traits>

template <typename T>
struct N
{
    N(T t) {}
};

struct base
{
    float f() const { return 0.f;}

    // using myN = N<decltype(std::bind(&base::f, std::add_pointer_t<std::declval<base> > ) ) >;
    // Error: tries to convert:
    // '_Bind<float (base::*(base*))() const>' to
    // '_Bind<float (base::*(base*&& (*)()))() const>'


    // using myN = N<decltype(std::bind(&base::f, std::declval<std::add_pointer_t<base> > ) ) >;
    // Error: tries to convert: 
    // '_Bind<float (base::*(base*))() const>' to 
    // '_Bind<float (base::*(base**&& (*)()))() const>'

    using myN = N<decltype(std::bind(&base::f, std::remove_reference<std::declval<std::add_pointer_t<base> > > ) ) >;
    // Error: tries to convert:
    // '_Bind<float (base::*(base*))() const>' to
    // '_Bind<float (base::*(std::remove_reference<base*>&& (*)()))() const>'

    void g()
    {
        auto boundMethod = std::bind(&base::f, this);
        myN n(boundMethod); // <-- this is the line with the errors mentioned above.
    }
};

限制:我仅限于 MSVC 2015,c++11。我一直在 godbolt 上使用 gcc 作为快速 MCVE,但生产项目使用 MSVC。

如何使类型匹配?

编辑:

使用 解决方案适用于 gcc,但在 MSVC 2015 中失败。我得到的错误是

error C2664:  
'N<std::_Binder<std::_Unforced,float (__thiscall base::* )(void) const,_Ty>>::N(N<std::_Binder<std::_Unforced,float (__thiscall base::* )(void) const,_Ty>> &&)': 
cannot convert argument 1 from  
'std::_Binder<std::_Unforced,float (__thiscall base::* )(void) const,base *const >' to  
'std::_Binder<std::_Unforced,float (__thiscall base::* )(void) const,_Ty>' 

为什么不直接 std::declval<base *>() 呢?

using myN = N<decltype(std::bind(&base::f, std::declval<base *>()))>;

请记住,您必须 "call" std::declval<Type>,才能获得 Type.

类型的对象

所以 std::declval<Type>(),而不是 std::declval<Type>

MSVC 似乎认为 this 是一个 const 右值指针,尽管它实际上不应该是 const,所以这将解决它:

using myN = N<decltype(std::bind(&base::f, std::declval<base* const>()))>;

但这可能会在其他地方破坏它。要强制 this 成为非常量右值,您还可以这样做:

using myN = N<decltype(std::bind(&base::f, std::declval<base*>()))>;

auto boundMethod = std::bind(&base::f, &*this);

另一种解决方案是改为绑定到引用(整体上更自然),并且您可能还想添加常量(这也解决了问题,因为它制作了指针的非常量副本)

using myN = N<decltype(std::bind(&base::f, std::declval<base&>()))>;
auto boundMethod = std::bind(&base::f, *this);


using myN = N<decltype(std::bind(&base::f, std::declval<const base*>()))>;
auto boundMethod = std::bind(&base::f, static_cast<const base*>(this));


// Or both
using myN = N<decltype(std::bind(&base::f, std::declval<const base&>()))>;
auto boundMethod = std::bind(&base::f, static_cast<const base&>(*this));