如何 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));
我正在尝试绑定 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。
如何使类型匹配?
编辑:
使用
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));