问题
I'm using ChaiScript 5.3.1, and I'm trying to bind functions to my own class, specifically a setPosition function which can take either a Vector3 or 3 floats.
The class and it's relevant methods are declared like so:
class DLLExport Actor
{
public:
Actor(Level* level, const String& name, Actor* parent);
virtual ~Actor();
void setPosition(const Real& x, const Real& y, const Real& z);
void setPosition(const Vector3& position);
};
and I'm trying to bind them like this:
m->add(user_type<Actor>(), "Actor");
m->add(fun<void (Actor::*)(const Vector3&)>(&Actor::setPosition), "setPosition");
This results in the following compiler output (Windows, MSVC 2013):
2functional(550): error C2027: use of undefined type 'std::_Get_function_impl<_Fty>'
2> with
2> [
2> _Fty=void (__thiscall Actor::* )(const Vector3 &)
2> ]
2> ..\..\ScriptingDemo\Binder.cpp(60) : see reference to class template instantiation 'std::function<void (__thiscall Actor::* )(const Vector3 &)>' being compiled
2functional(551): error C2504: 'type' : base class undefined
2functional(554): error C2027: use of undefined type 'std::_Get_function_impl<_Fty>'
2> with
2> [
2> _Fty=void (__thiscall Actor::* )(const Vector3 &)
2> ]
2functional(554): error C2146: syntax error : missing ';' before identifier '_Mybase'
2functional(554): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
回答1:
This is a compiler bug. Clang and GCC both accept this SSCCE, Visual C++ does not.
The four overloaded functions chaiscript::fun
are declared as so:
/*1*/ template <typename T>
Proxy_Function fun (T t);
/*2*/ template <typename T>
Proxy_Function fun (const std::function< T > &f);
/*3*/ template <typename T, typename Q>
Proxy_Function fun (T t, const Q &q);
/*4*/ template <typename T, typename Q, typename R>
Proxy_Function fun (T t, const Q &q, const R &r);
According to the language rules, this expression:
fun<void (Actor::*)(const Vector3&)>(&Actor::setPosition)
Results in a call to either overload 1 or overload 2, overload resolution will determine which.
After substituting the explicit template argument, this is what overload resolution will have to work with:
/*1*/ Proxy_Function fun (void (Actor::*)(const Vector3&) t);
/*2*/ Proxy_Function fun (const std::function< void (Actor::*)(const Vector3&) > &f);
std::function< void (Actor::*)(const Vector3&) >
is an undefined type, so overload 2 is not viable. Visual C++ seems to think that this constitutes an error, but it should not.
With your workaround:
fun((void(Actor::*)(const Vector3&))&Actor::setPosition)
You are casting the pointer to overloaded member function &Actor::setPosition
to the type void(Actor::*)(const Vector3&)
and allowing template argument deduction to step in, and Visual C++ is content with that.
You would be even better off avoiding C-style casts:
fun(static_cast<void(Actor::*)(const Vector3&)>( &Actor::setPosition ))
回答2:
Not sure how, exactly but I fixed it like this:
m->add(fun((void(Actor::*)(const Vector3&))&Actor::setPosition), "setPosition");
I'm just glad I found an answer, if someone would explain why this works it'd be great.
来源:https://stackoverflow.com/questions/25488297/binding-functions-with-multiple-arguments-results-in-c2027