"term does not evaluate to a function taking X arguments"

Started by xxh, 24 May 2016, 23:46:36

xxh

- What compiler version are you using? Visual Studio 2013 update 5
- Did you download the precompiled libraries, or did you build from source? precompiled
- Are you linking statically, or dynamically? statically
- If needed/possible, provide a complete but minimal example that I can test.

I've tried modifying and using multiple examples, tutorials on the site into a class. But every time I try to do a signal ->connect
e.g.     button->connect("pressed", &MyClass::login, editBoxUsername, editBoxPassword);
or even removing the parameters (button->connect("pressed", &MyClass::login)
I get the error
Error   2   error C2064: term does not evaluate to a function taking 2 arguments   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional   1149   1   
or 0 arguments... any arguments. It doesn't seem to like the binding, and I have no idea how to fix this.

texus

The issue is that VS2013 does not support expression SFINAE yet while the online examples are already using it. Any GCC compiler since 2013 can compile that code but Visual Studio only added support for it 2 months ago with VS2015 Update 2. The example code on the website uses the unbound parameters feature of the connect function which is not supported in VS2013.

Of course removing these two parameters in the connect call is giving you the other error because you are then calling a function with less parameters than it needs.

Since you are the second person to mention something like this I will change my online examples tomorrow (or somewhere this week) to make it work with VS2013 as well. In the meantime you can check the "examples" folder in the TGUI folder that you downloaded, they do compile on VS2013.

xxh

Alright, thank you for the info. And sorry I didn't see the other person inquiring about it.

I've looked through the examples a bit, but I can't seem to find a way to get events (e.g. button clicks) from the GUI without ->connect (which doesn't work)
Is there another method to call functions when a GUI component is clicked? Or a workaround of some kind?
Maybe I'm missing something here...

Would appreciate your help.

texus

Since it contains all the info you are asking for I'll just link to this existing answer: https://forum.tgui.eu/index.php?topic=424.msg2282#msg2282

In short: the connect function does function, just not a specific use case of it. You could even bind the parameters yourself but that requires knownledge on std::bind. But without binding parameters manually you can still get data back from the widget with connectEx.

xxh

Okay, I tried changing it up a bit.

void ConnectionScreen::login(std::string username, std::string password)

button->connect("pressed", &ConnectionScreen::login, "test", "test"); //passing it manually

button->connect("pressed", &ConnectionScreen::login, editBoxUsername->getText(), editBoxPassword->getText()); //testing if I can get the text from the editbox directly instead of passing the editbox


but these both give me the same error...

Am I doing it wrong?

texus

I wrongly assumed that this was the same issue as the one reported last week as they looked similar on first sight (both about the online examples with VS2013), but this is apparently a different issue.

I just checked and realized that the scalable login screen example doesn't use unbound parameters.

From your last post the second connect call is not valid c++ but lets focus on the first call for now because it should work (just like the original code). The error you showed is normal for when the parameters are gone, but if I understood you correctly you also get "C2064: term does not evaluate to a function taking 2 arguments" when passing these "test" strings? Could you show the full compiler output?

xxh

Yes, with the two "test" strings I get that error.
Error   2   error C2064: term does not evaluate to a function taking 2 arguments   c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional   1149   1   GameTwo.Client

Quote1>------ Build started: Project: GameTwo.Client, Configuration: Debug Win32 ------
2>------ Build started: Project: GameTwo.Common, Configuration: Debug Win32 ------
2>  GameTwo.Common.vcxproj -> E:\Dev\Coding\Projects\GameTwo\GameTwo\Debug\GameTwo.Common.lib
1>  ConnectionScreen.cpp
1>e:\dev\coding\projects\gametwo\gametwo\src\connectionscreen.cpp(52): warning C4244: 'argument' : conversion from 'unsigned int' to 'float', possible loss of data
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(1149): error C2064: term does not evaluate to a function taking 2 arguments
1>          class does not define an 'operator()' or a user defined conversion operator to a pointer-to-function or reference-to-function that takes appropriate number of arguments
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(1137) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>::_Do_call<,0,1>(std::tuple<>,std::_Arg_idx<0,1>)' being compiled
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(1137) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>::_Do_call<,0,1>(std::tuple<>,std::_Arg_idx<0,1>)' being compiled
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(283) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>::operator ()<>(void)' being compiled
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(283) : see reference to function template instantiation 'void std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>::operator ()<>(void)' being compiled
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>,false>::_ApplyX<_Rx,>(void)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Rx=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(228) : see reference to function template instantiation '_Ret std::_Callable_obj<std::_Bind<true,_Ret,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>,false>::_ApplyX<_Rx,>(void)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Rx=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(226) : while compiling class template member function 'void std::_Func_impl<_MyWrapper,_Alloc,_Ret,>::_Do_call(void)'
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Ret=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(495) : see reference to class template instantiation 'std::_Func_impl<_MyWrapper,_Alloc,_Ret,>' being compiled
1>          with
1>          [
1>              _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Ret=void
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(396) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Do_alloc<_Myimpl,_Ty,_Alloc>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(385) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset_alloc<_Ty,std::allocator<std::_Func_class<_Ret,>>>(_Fty &&,_Alloc)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Alloc=std::allocator<std::_Func_class<void,>>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>          ]
1>          c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional(671) : see reference to function template instantiation 'void std::_Func_class<_Ret,>::_Reset<_Ty>(_Fty &&)' being compiled
1>          with
1>          [
1>              _Ret=void
1>  ,            _Ty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>  ,            _Fty=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>          ]
1>          e:\dev\coding\lib\tgui-0.7\include\tgui\signal.hpp(153) : see reference to function template instantiation 'std::function<void (void)>::function<std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>          ]
1>          e:\dev\coding\lib\tgui-0.7\include\tgui\signal.hpp(153) : see reference to function template instantiation 'std::function<void (void)>::function<std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>>(_Fx &&)' being compiled
1>          with
1>          [
1>              _Fx=std::_Bind<true,void,std::_Pmf_wrap<void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string),void,g2c::ConnectionScreen,std::string,std::string>,const char *&,const char *&>
1>          ]
1>          e:\dev\coding\lib\tgui-0.7\include\tgui\signal.hpp(152) : while compiling class template member function 'std::function<void (void)> tgui::priv::connector<type,Func,const char *,const char *>::connect(Func,size_t,const char *,const char *)'
1>          with
1>          [
1>              Func=void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string)
1>          ]
1>          e:\dev\coding\lib\tgui-0.7\include\tgui\signal.hpp(240) : see reference to function template instantiation 'std::function<void (void)> tgui::priv::connector<type,Func,const char *,const char *>::connect(Func,size_t,const char *,const char *)' being compiled
1>          with
1>          [
1>              Func=void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string)
1>          ]
1>          e:\dev\coding\lib\tgui-0.7\include\tgui\signal.hpp(240) : see reference to class template instantiation 'tgui::priv::connector<type,Func,const char *,const char *>' being compiled
1>          with
1>          [
1>              Func=void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string)
1>          ]
1>          e:\dev\coding\lib\tgui-0.7\include\tgui\signal.hpp(354) : see reference to function template instantiation 'void tgui::Signal::connect<Func,const char*,const char*>(unsigned int,Func,const char *,const char *)' being compiled
1>          with
1>          [
1>              Func=void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string)
1>          ]
1>          e:\dev\coding\projects\gametwo\gametwo\src\connectionscreen.cpp(146) : see reference to function template instantiation 'unsigned int tgui::SignalWidgetBase::connect<void(__thiscall g2c::ConnectionScreen::* )(std::string,std::string),const char*,const char*>(const std::string &,Func,const char *,const char *)' being compiled
1>          with
1>          [
1>              Func=void (__thiscall g2c::ConnectionScreen::* )(std::string,std::string)
1>          ]
========== Build: 1 succeeded, 1 failed, 1 up-to-date, 0 skipped ==========

texus

It took me a while to figure it out but I think I know what is going wrong (the compile error isn't very helpful).

You are not passing enough parameters to the connect function. Since the function is a class member, there is a hidden "this" parameter that has to be provided. Check the "connecting member functions" part of the signal tutorial.
Your code should have been like this:
Code (cpp) Select
ConnectionScreen screen;
button->connect("pressed", &ConnectionScreen::login, &screen, "test", "test");


The correct form for the one with the getText calls would be the following (manual std::bind is required as there have to be 2 bind calls of which tgui only performs one).
Code (cpp) Select
button->connect("pressed", &ConnectionScreen::login, &screen, std::bind(&tgui::EditBox::getText, editBoxUsername), std::bind(&tgui::EditBox::getText, editBoxPassword));

But the original code should have worked if you would have pass the hidden "this" pointer to the connect function as well. There isn't anything that I can do it TGUI to make it easier, it is a c++ detail that you have to know when passing function pointers.

xxh

Nice. The first one works.

However, the second with the std::binds gives me:
Quoteerror C3848: expression having type 'const std::_Bind<true,sf::String,std::_Pmf_wrap<sf::String (__thiscall tgui::EditBox::* )(void) const,sf::String,tgui::EditBox,>,tgui::EditBox::Ptr &>' would lose some const-volatile qualifiers in order to call 'sf::String std::_Bind<true,sf::String,std::_Pmf_wrap<sf::String (__thiscall tgui::EditBox::* )(void) const,sf::String,tgui::EditBox,>,tgui::EditBox::Ptr &>::operator ()<>(void)'   e:\dev\coding\lib\tgui-0.7\include\tgui\signal.hpp   191   1   GameTwo.Client

Really appreciate your (fast) help with this by the way. Thanks so much.

texus

It seems to work here (I didn't test it when I wrote it but I tested it now).

Maybe the compiler doesn't like the parameter conversion (editBox->getText() returns sf::String and your parameters are std::string), you could try making the parameters sf::String. Another thing that might be an issue is that the edit boxes are smart pointers instead of normal pointers, so you could also try writing "editBoxUsername.get()" instead of "editBoxUsername" (and the same for editBoxPassword). But if that doesn't work then I don't know why it doesn't work, it could of course just be something that isn't supported in VS2013.

xxh

Well, I couldn't get either of those things to compile. I tried a few other things too.

I went back to trying    button->connect("pressed", &ConnectionScreen::login, this, editBoxUsername->getText(), editBoxPassword->getText()); and it actually works fine!

However, I have an unrelated problem. I'm not getting keyboard input in the EditBoxes. I can do ->setText() and it changes. I checked that the events are being pushed through
very strange..

I basically have
class ConnectionScreen : public g2c::GameScreen
{
...
private:
tgui::Gui _gui;
};

...

ConnectionScreen::ConnectionScreen(sf::RenderWindow& window) : GameScreen(window)
{
//ctor
_gui.setWindow(window);
}

(load content) -> loadWidgets(_gui);

void ConnectionScreen::updateEvent(sf::Event event)
{
.............
_gui.handleEvent(event);
.....
}


And the rest is the login example.

The typing/blinking cursor shows up when I click the boxes. But no keys input text to the boxes.  :o

EDIT: Backspace works, but nothing else does. Also if I backspace the text I used with setText, I still get the old text to the login function...

texus

QuoteI went back to trying    button->connect("pressed", &ConnectionScreen::login, this, editBoxUsername->getText(), editBoxPassword->getText()); and it actually works fine!
I was apparently a little bit too quickly to say that it was invalid code. You are right, it is perfectly valid code, it just doesn't do what you might expect.
If you pass "editBoxUsername->getText()" then the compiler will call that getText fuction (before calling your connect function) and store this string. When the callback function is called then the parameters are always the value of the edit box at the moment you called the connect function instead of containing the value of the edit box at the moment the callback itself occurs. The std::bind variant will not call the function immediately but really pass the function pointer itself. In this case when the callback occurs the getText function is called and its return value is passed as parameter to the callback function. So the parameters are only up-to-date when the function is bound (or when passing a reference but that is not possible since you want to use a return value of a function).

QuoteI have an unrelated problem. I'm not getting keyboard input in the EditBoxes.
That is indeed strange. Could you show the full code so that I can just copy-paste and try it here?

xxh

QuoteYou are right, it is perfectly valid code, it just doesn't do what you might expect.
If you pass "editBoxUsername->getText()" then the compiler will call that getText fuction (before calling your connect function) and store this string

That explains my edit about the text not changing. Damn, so I still don't have a solution.

QuoteCould you show the full code so that I can just copy-paste and try it here?
I'll have to mock up something similar that's simpler/smaller. Give me a bit.

xxh

Haha. As I was looking through all the code and copying it for you, I found the problem. I was using an else statement for textEntered because I have a separate input manager, and it was the only event not being passed to the screens.
My bad.  :P

Now if I could just find a way to pass the current text.
It seems I might have to put the editboxes in my class like
private:
tgui::EditBox::Ptr editBoxUsername;
then getText in the login function.
but would this work?
how will I set the theme (after), is that a problem?

texus

QuoteNow if I could just find a way to pass the current text.
What about just passing the edit boxes themselves as parameter like the original example code did?

Quotehow will I set the theme (after), is that a problem?
I'm not sure what you mean with "after", depending on what you mean there might be problems though. In the code that I am developing for v0.8 there will be an easy way to reload the theme of the widget after its creation but I don't think there is an easy way in the v0.7 renderer system without manually copying the renderer properties.
If you put "tgui::EditBox::Ptr editBoxUsername;" in the class and then in the constructor (or anywhere before you use the edit box) call "editBoxUsername = theme->load(...)" then there will be no problems. But you can't first connect it and then run theme->load afterward because then you replace the edit box (and it would be a nullptr when calling connect as well).