I'm trying to bind a method of a class and to pass it as a template parameter to a different class. This type needs to be used in multiple methods, so I tried using a using
clause in the class (struct base
below).
However, I'm not really able to get the type right. These are (most of) what I've tried so far:
#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.
}
};
Limitations: I'm restricted to MSVC 2015, c++11. I've been using gcc on godbolt as quick MCVE, but the production project is with MSVC.
How do I get the types to match up?
Using max66's solution(s) works for gcc, but fails with MSVC 2015. The error I get is
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>'
Why not simply std::declval<base *>()
?
using myN = N<decltype(std::bind(&base::f, std::declval<base *>()))>;
And remember you have to "call" std::declval<Type>
, to obtain an object of type Type
.
So std::declval<Type>()
, not std::declval<Type>
.