While doing some random-ish, weird-ish things to understand a little bit more C++ (just to say I'm still a newbie), I came across something I can't properly understand : I'm currently using SFML which provides a few methods to create and manage a window, namely this method to close it: void sf::RenderWindow::close(). It doesn't take any argument, and it can't be called directly but through an instantiated object.
sf::RenderWindow::close(); // error
My problem is the following code :
sf::RenderWindow window(sf::VideoMode(800, 600), "test"); // added after edit
const std::function <void(sf::RenderWindow &)> callback(sf::RenderWindow::close);
// callback();
callback(window); // closes the window
I'm not sure to understand what's happening here as I'm not using any object... even anonymous at first sight... I guess...
If someone can enlighten me, I'd really appreciate it.
Thanks you.
Edit:
My mistake, yes there's an object.
#include <iostream>
#include <functional>
#include <SFML/Graphics.hpp>
int main()
{
sf::RenderWindow window(sf::VideoMode(800, 600), "test");
const std::function <void(sf::RenderWindow &)> call(sf::RenderWindow::close);
call(window);
return 0;
}
Actually, I understand this as if it were sf::RenderWindow::close(window), similarly to metatables in lua I suppose.
It's linked to the concept of Callable:
Since the stored target of the std::function (i.e. sf::RenderWindow::close) is a pointer to member function and the first argument (i.e. window) is a (reference to) an object of type RenderWindow, then the invocation of the function object is equivalent to window.close().
You could also have written something along those lines:
std::function<void(sf::RenderWindow*)> call = &sf::RenderWindow::close;
call(&window);
Below a code sample that doesn't involve SFML:
#include <iostream>
#include <functional>
class Window {
public:
void close() {std::cout << "close" << std::endl; }
};
int main(int argc, const char * argv[]) {
Window w;
std::function<void(Window&)> f = &Window::close;
f(w);
std::function<void(Window*)> g = &Window::close;
g(&w);
return 0;
}
Related
Here's my scenario:
main.cpp
#include <Windows.h>
#include <functional>
std::function<void()> OnPrepare;
int WINAPI WinMain(HINSTANCE inst, HINSTANCE preInst, TCHAR*, int) {
if (OnPrepare) {
OnPrepare();
}
return 0;
}
other.cpp
#define _AFXDLL
#include <afx.h> // TRACE
#include <functional>
extern std::function<void()> OnPrepare;
class Init {
public:
Init() {
OnPrepare = []() {
TRACE("hello, world!\n");
};
}
};
Init g_init;
This code does not work in a Win32 application, but works well in a Console application. I don't know why. Can anyone point out what's wrong with my code? If I can't do it like this, is there a better way?
EDIT:
OnPrepare is always null in a Win32 application, so no "hello, world" will appear.
The code for constructingg_init modifies OnPrepare. This is, of course, only legal if OnPrepare has already been constructed. But what if g_init is constructed before OnPrepare? Then you'll be modifying an object that hasn't been constructed yet and then later constructing an object you've already modified. Ouch. Doing real work in the constructors of static objects is never a good idea.
It's not clear what your outer problem is, but this code isn't a good way to solve it. An ugly workaround is to replace your global std::function with a global function that returns a reference to a function static std::function and use that. That ensures the object is constructed before being assigned to.
std::function<void()>& getOnPrepare()
{
static std::function<void()> OnPrepare;
return OnPrepare;
}
Then the constructor of Init can call getOnPrepare, ensuring that OnPrepare is constructed before it's assigned to:
Init() {
getOnPrepare() = []() {
TRACE("hello, world!\n");
};
I would like to know if there was a way to declare a class before a function, and then initialize it inside of a function, something like this:
Application.h:
class Application
{
Application(HWND hwnd);
~Application() {}
};
Main.cpp:
#include "Application.h"
#include <Windows.h>
Application App;
int main()
{
App(hwnd);
return 0;
}
Application *pApp;
int main()
{
pApp = new Application(hwnd);
//use pApp
delete pApp;
return 0;
}
Using a pointer is pretty much the only way to do what you want to do.
You cannot initialize a global object inside a function, the constructor of the object will be called some time before the main function of the program is called. This is very bad, it involves the thing called static initialization fiasco and you want to avoid it. Try to search for singleton pattern implementation in C++, that's what you need probably.
In C++ the constructor for an object is called when the storage for it is allocated, you cannot call the constructor later like you tried to do.
You might consider not defining a constructor, and using a separate member function, for example init, to initialize your App object.
Application.h:
class Application
{
public:
void init(HWND hwnd);
};
Main.cpp:
#include "Application.h"
#include <Windows.h>
Application App;
int main()
{
App.init(hwnd);
return 0;
}
So, I'm trying to compile my code, but the compiler keeps complaining that "'mysnake' undeclared (first use this function)", but I declared it.
This is my Main.cpp, wehre it is declared.
#include "Class.h"
#include "Snake.h"
int main(int argc, char* args[]){
Prog run;
if((run.Init())==false){
return(1);
}
Snake mysnake;
if(run.LoadFiles()==false){
return(1);
}
run.MainLoop();
if(run.Draw()==false){
return(1);
}
run.CleanUp();
return(0);
}
And this is the file that makes the compiler complain (AFAIK it's the first file with any reference to 'mysnake' that gets compiled)
#include "Class.h"
#include<sstream>
#include "Snake.h"
bool Prog::Draw(){
std::stringstream message;
SDL_Rect position;
SDL_BlitSurface(image, NULL, screen, NULL);
int s=mysnake.EndSnake();
message<<"Your snake was "<<s<<" blocks long.";
msg=TTF_RenderText_Solid(font, message.str().c_str(), font_color);
if(msg==NULL){
return(false);
}
position.x=(WWIDTH-msg->w)/2;
position.y=(WHEIGHT-msg->h)/2;
SDL_BlitSurface(msg, NULL, screen, &position);
SDL_Flip(screen);
return(true);
}
I have thought about it for over an hour and I still can't understand why it does this. By the way I'm using Bloodshed Dev C++
I'd be very grateful for help.
Inside your Draw function there is no variable declared called mysnake. That function can't see the mysnake that's declared in main because it is local to main. You need to pass your mysnake object to the Draw function so that it knows which snake you're actually talking about.
To do that, give Draw an argument of type const Snake&, a "reference to const Snake" (or take away the const if EndSnake is a non-const member function):
bool Prog::Draw(const Snake& snake) {
// ...
}
And when you call Draw in main, do this:
run.draw(mysnake);
Now your Draw function has a variable called snake which was passed in from main. Because the argument is a reference, the Snake object that it sees is exactly the same object as in main. If the argument had been of type Snake instead of const Snake&, then you would get a copy of the mysnake from main.
Some extra advice:
We usually write conditions like (run.Init())==false as just !run.init() - it reads much better. Returning is also usually written as return true;, rather than return(true);, but that's up to you.
The fact that mysnake is declared in main does not allow one to use it in Prog. You probably want to transmit a reference to mysnake to the Draw method.
Through the constructor or through the call to the method.
Prog run(mysnake);
run.draw();
or
run.draw(mysnake);
Still working on my closed/open source hybrid talked about earlier in this question. The application in question is actually a busybox like application -- there are several programs bundled into a single program, and the actual program run is chosen based upon the first command entered. This allows the sub-programs to share one copy of the CRT (I can't use the installable redist because I need to maintain single binary deployment), as well as several internals which are useful in several of the sub programs.
Because some of the sub programs themselves cannot be released as a result of licensing restrictions, I'm considering using a startup like this. (Sorry for the amount of code :( )
ISubProgram.hpp
#include <string>
struct ISubProgram
{
virtual std::wstring GetExecutive() const = 0; //Return sub program name
virtual void OnStart(int argc, const char *argv[]) {};
virtual int Run(int argc, const char *argv[]) = 0;
virtual ~ISubProgram() {}
};
SubProgramList.hpp
#include <memory>
#include <boost/ptr_container/ptr_map.hpp>
#include <boost/noncopyable.hpp>
#include "ISubProgram.hpp"
class SubProgramList;
SubProgramList& GetSubProgramList();
class SubProgramList : boost::noncopyable
{
friend SubProgramList& GetSubProgramList();
SubProgramList() {} //Disallow direct creation.
boost::ptr_map<std::wstring,ISubProgram> programs;
public:
void RegisterProgram(std::auto_ptr<ISubProgram> subProgramToRegister);
ISubProgram * FindProgramFromExecutive(const std::wstring& executive);
void CallOnStartMethods(int argc, char *argv[]);
};
template <typename T>
struct RegisterSubProgram
{
RegisterSubProgram()
{
std::auto_ptr<ISubProgram> toAdd(new T);
GetSubProgramList().RegisterProgram(toAdd);
}
}
SubProgramList.cpp
SubProgramList& GetSubProgramList()
{
static SubProgramList theList;
return theList;
}
//Implementations of the class methods
ExampleSubProgram.cpp
#include "SubProgramList.hpp"
struct ExampleSubProgram : public ISubProgram
{
virtual std::wstring GetExecutive()
{
return L"ExampleSubProgram";
}
virtual int Run(int argc, const char *argv[])
{
//Run this program :)
}
};
namespace { RegisterSubProgram<ExampleSubProgram> registrar; }
Main.cpp
#include "SubProgramList.hpp"
int main(int argc, char *argv[])
{
SubProgramList& list = GetSubProgramList();
list.CallOnStartMethods(argc, argv);
std::wstring subProgramName(/*.. Generate from argv[1] ...*/);
FindProgramFromExecutive(subProgramName)->Run(argc, argv);
}
I think I'm clear of initialization order issues because the only global state is a local static rather than a global static.
The main reason for this is that I can completely pull apart the closed source and open source bits of the program, which would make merging quick and efficient, and also removes the boilerplate of my current "Giant if/else subprogram selector" in main.
Is this a reasonable use of on-start initialization (which is generally discouraged?) If not, what alternate implementation would you suggest?
I could come up with some clever programs with recursive template instantiation, but the reality is that what you've done is probably simpler than what I can come up with. It's rare that I suggest that global state is a smart idea, but on this one I may have to accept that I can't do better.
Dear all, I would like to call a member function (that expects a reference) for each object of (let's say) a vector that is a member of the same class, as the following code shows:
#include <functional>
#include <algorithm>
#include <vector>
#include <iostream>
using namespace std;
struct Stuff {
double x;
};
class Test {
public:
void f1(Stuff & thing);
void f2(void);
vector<Stuff> things;
};
void Test::f1(Stuff & thing) {
; // do nothing
}
void Test::f2(void) {
for_each(things.begin(), things.end(), f1);
}
int main(void)
{
return 0;
}
This codes gives me a compiler error related to unresolved overloaded function type . I have tried also with bind, but it seems that the references requisite in f1 is one problem. I know I am missing something important here, so I take this opportunity to solve my problem and to learn. At the moment, I can't install boost, but I would like to know also if boost is useful to solve this problem. Thanks in advance.
The function you want to call cannot be simply identified by f1 but should be referred to as &Test::f1 (as in : member function f1 of class Test)
Function f1 does not take a single argument : as any non-static member function it has an implicit this parameter of type Test * const
Finally, a standard bind won't be able to do the trick because it doesn't handle parameters passed by reference.
Boost.Bind would indeed be a great option :
std::for_each(things.begin(), things.end(), boost::bind(&Test::f1, this, _1));