Связывание функций с несколькими аргументами приводит к C2027

Я использую ChaiScript 5.3.1 и пытаюсь привязать функции к своему собственному классу, в частности, к функции setPosition, которая может принимать плавающие значения Vector3 или 3.

Класс и его соответствующие методы объявлены так:

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);
};

и я пытаюсь связать их так:

m->add(user_type<Actor>(), "Actor");
m->add(fun<void (Actor::*)(const Vector3&)>(&Actor::setPosition), "setPosition");

Это приводит к следующему выводу компилятора (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

0

Решение

Это ошибка компилятора. Clang и GCC оба принимают это SSCCE, Visual C ++ не делает.

Четыре перегруженные функции chaiscript::fun объявлены так:

/*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);

Согласно правилам языка, это выражение:

fun<void (Actor::*)(const Vector3&)>(&Actor::setPosition)

Приводит к вызову либо перегрузки 1, либо перегрузки 2, разрешение которой будет определять, какое именно.

После подстановки явного аргумента шаблона вот с чем должно работать разрешение перегрузки:

/*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&) > является неопределенным типом, поэтому перегрузка 2 нежизнеспособна. Visual C ++, похоже, считает, что это является ошибкой, но не должно.

С вашим обходным путем:

fun((void(Actor::*)(const Vector3&))&Actor::setPosition)

Вы приводите указатель на перегруженную функцию-член &Actor::setPosition к типу void(Actor::*)(const Vector3&) и позволяющий вмешиваться в аргументы шаблона, и Visual C ++ доволен этим.

Вы бы даже лучше избегали бросков в стиле C:

fun(static_cast<void(Actor::*)(const Vector3&)>( &Actor::setPosition ))
2

Другие решения

Не уверен, как именно, но я исправил это так:

m->add(fun((void(Actor::*)(const Vector3&))&Actor::setPosition), "setPosition");

Я просто рад, что нашел ответ, если кто-то объяснит, почему это работает, было бы здорово.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector