0

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
Ilija Boshkov
  • 149
  • 2
  • 10
  • Is `fun` the same as `std::function` ? – Piotr Skotnicki Aug 25 '14 at 14:38
  • No, fun is a ChaiScript function (to be precise I'm using it from a chaiscript::Module(ptr)) See this: http://chaiscript.com/docs/5/namespacechaiscript.html#a762c1923df6b87198036c01cf824cb53 – Ilija Boshkov Aug 25 '14 at 14:42
  • I'm basing my approach on the details defined here: http://chaiscript.com/docs/5/index.html#addingfunctions (Overloaded function binding) – Ilija Boshkov Aug 25 '14 at 14:44
  • 2
    Somehow, somewhere, you have a typedef or macro that makes `fun` mean `std::function`. You are not invoking `chaiscript::fun`. Figure out why. – Igor Tandetnik Aug 25 '14 at 15:07
  • @igor-tandetnik Yep, seems like this particular definition was using an std::function. I looked up the definitions and this is what popped up: http://i.imgur.com/4Ye1nuC.png. Now to figure out how to actually bind a function without linking it to a particular object. – Ilija Boshkov Aug 25 '14 at 15:30
  • This [answer ](http://stackoverflow.com/a/7582574/878466)seems to point to this being the way to do it: `std::function setPos = &Crimson::Actor::setPosition;` (adapted from the info in the upvoted answer) – Ilija Boshkov Aug 25 '14 at 15:40

2 Answers2

2

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 ))
Oktalist
  • 14,336
  • 3
  • 43
  • 63
0

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.

Ilija Boshkov
  • 149
  • 2
  • 10