I'm trying to implement a custom event in my wxWidgets application but I can't write the event table macros in a proper way.
the files that I use to implement the event is like the following:
the .h file
#ifndef __APP_FRAME_H__
#define __APP_FRAME_H__
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include <wx/evtloop.h>
#include "wxApp.h"
#include "sampleCefApp.h"
class appFrame: public wxFrame
{
public:
appFrame(const wxString &title, const wxPoint &pos, const wxSize &size);
private:
int OnExit();
void OnCefStartEvent(wxCommandEvent &e);
DECLARE_EVENT_TABLE()
};
#endif
the .cpp file
// File : appFrame.cpp
#include "appFrame.h"
wxDEFINE_EVENT(CEF_START_EVT, wxCommandEvent)
void appFrame::OnCefStartEvent(wxCommandEvent &e)
{
CefRunMessageLoop();
}
int appFrame::OnExit(){
CefShutdown();
Destroy();
return 0;
}
appFrame::appFrame(const wxString &title, const wxPoint &pos, const wxSize &size)
: wxFrame(NULL, wxID_ANY, title, pos, size)
{
}
wxBEGIN_EVENT_TABLE(appFrame, wxFrame)
EVT_COMMAND(wxID_ANY, CEF_START_EVT, appFrame::OnCefStartEvent)
wxEND_EVENT_TABLE()
And when I build my make file I get the following errors:
../src/appFrame.cpp:4:15: error: expected constructor, destructor, or type conversion before ‘(’ token
../src/appFrame.cpp:24:2: error: expected constructor, destructor, or type conversion before ‘wxEventTableEntry
I think the problem is related to mis-placing event table macros.
I want to know what is the problem exactly and how to fix it ?
You need a semicolon after wxDEFINE_EVENT() macro (as for almost all macros with wx prefix, they consistently require a semicolon, unlike the legacy macros without the prefix).
As usual, see the sample for the example of use of this macro.
Related
I know it was discussed in length many times already, but my case has some particular condition I don't know how to address properly.
Library with /MDd solution builds OK. But it is not what the application needs as it requires /MT(d) version.
Now, I've changed the compiler options to /MTd, resolved some of the external projects dependencies, but still getting this:
Error LNK2019 unresolved external symbol "bool __cdecl std::uncaught_exception(void)" (?uncaught_exception#std##YA_NXZ) referenced in function "public: __cdecl std::basic_ostream<char,struct std::char_traits<char> >::sentry::~sentry(void)" (??1sentry#?$basic_ostream#DU?$char_traits#D#std###std##QEAA#XZ) vcruntime140 ..\vcruntime140 ..\vcruntime140\log.obj
log.h is just this:
#ifndef LOG_H
#define LOG_H
#include <string>
namespace hooks {
/** Prints message to the file only if debug mode setting is enabled. */
void logDebug(const std::string& logFile, const std::string& message);
/** Prints message to the file. */
void logError(const std::string& logFile, const std::string& message);
} // namespace hooks
#endif // LOG_H
log.cpp
#include "log.h"
#include <chrono>
#include <ctime>
#include <fstream>
#include <iomanip>
namespace hooks {
static void logAction(const std::string& logFile, const std::string& message)
{
using namespace std::chrono;
std::ofstream file(logFile.c_str(), std::ios_base::app);
const std::time_t time{std::time(nullptr)};
const std::tm tm = *std::localtime(&time);
file << "[" << std::put_time(&tm, "%c") << "] " << message << "\n";
}
void logDebug(const std::string& logFile, const std::string& message)
{
logAction(logFile, message);
}
void logError(const std::string& logFile, const std::string& message)
{
logAction(logFile, message);
}
} // namespace hooks
hooks.h
#ifndef HOOKS_H
#define HOOKS_H
#include <string>
#include <utility>
#include <vector>
namespace hooks {
using HookInfo = std::pair<void**, void*>;
using Hooks = std::vector<HookInfo>;
/** Returns array of hooks to setup. */
Hooks getHooks();
Hooks getVftableHooks();
} // namespace hooks
#endif // HOOKS_H
hooks.cpp
#include "hooks.h"
namespace hooks {
Hooks getHooks()
{
Hooks hooks;
return hooks;
}
Hooks getVftableHooks()
{
Hooks hooks;
return hooks;
}
} // namespace hooks
Any idea of how to resolve it?
Found solution, the only remaining issue is actually unrelated to the above. The above errors are resolved in the following way:
Adding MSVCPRTD.LIB to the additional libraries link seem to elliminate the problems with LINK2019.
The problem was happening since some of the standard library functions defined in that lib were not loaded. I've realised it by checking the error message and googling of which function definitions are missing and which library they belong to.
But now there is a problem with MSVCPRTD.LIB as it is a dynamic and not a static library according to Microsoft docs: https://learn.microsoft.com/en-us/cpp/c-runtime-library/crt-library-features?view=msvc-160
The problem with MSVCPRTD.LIB can be addressed by loading libcmtd.lib instead, which is the /MTd version of the same librari(es).
I'm currently trying to playaround with operator overloading and built the following code
//Circle.cpp
//Circle.cpp
#ifndef CIRCLE_H
#define CIRCLE_H
#include "IOD.cpp"
#include<string>
class IOD; //Forward declaration
class Circle
{
public:
void display(IOD& ioDevice) const
{
ioDevice<<*this;
}
};
#endif
//IOD.cpp
//IOD.cpp
#ifndef IOD_H
#define IOD_H
#include <iostream>
#include<string>
#include "Circle.cpp"
class Circle; //Forward declaration
class IOD
{
// Interface for displaying CAD objects
public:
void operator<<(const Circle& c)
{
std::cout << "Displaying the object Circle Using IODevice GraphicsScreen for circles";
}
};
#endif
//Source.cpp
//Source.cpp
#include <iostream>
#include "Circle.cpp"
#include "IOD.cpp"
int main()
{
Circle* c1 = new Circle();
IOD* d1 = new IOD();
c1->display(*d1);
}
I'm trying to have the display function in Circle to call the overloaded operator << in IOD to print output about the Circle object to the screen. My understanding is that using "ioDevice<<*this" inside the display function should produce the desired output. But instead i'm getting the following error
error C2676: binary '<<': 'IOD' does not define this operator or a conversion to a type acceptable to the predefined operator
Any workarounds to this?
You have circular dependency between files: Circle.cpp includes IOD.cpp and vice versa.
In order to make it work fine you should split your cpp files into cpp and .h where .h will include only API definitions.
You should think of #include as "copy-paste".
#include <iostream>
#include <fstream>
#include <type_traits>
#include <Windows.h>
#include "abase.h"
using namespace std;
class Storage {
string _path;
public:
Storage(string path);
~Storage() = default;
template <typename T >
bool writeFile(string fileName,
typename enable_if<is_base_of<ABase, T>::value, T >::type* data);
}
Definition...
#include "storage.h"
Storage::Storage(string path)
{
this->_path = path;
}
template <typename T >
bool Storage::writeFile(string fileName,
typename enable_if<is_base_of<ABase, T>::value, T >::type* data){
return true;
}
Im still getting error by Linker:
LNK2019 unresolved external symbol "public: bool __thiscall
Storage::writeFile(class std::basic_string,class std::allocator >,class AFile*)"
(??$writeFile#VAFile###Storage##QAE_NV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##PAVAFile###Z)
referenced in function _main
Why am i getting it if code is looking right. Its generic definition of method in a class and Im trying to constrain class type passing to the method.
And the AFile is inherited from ABase.
ABase is abstract class.
Simple usage in main:
Storage* s = new Storage("C:\\aPath...");
AFile* afile = new AFile();
s->writeFile<AFile>("a.txt", afile);
To solve your linking error you can explicitly instantiate[1] your template member function in the Storage.cpp like this:
template
bool Storage::writeFile<AFile>(string fileName,
enable_if<is_base_of<ABase, AFile>::value, AFile>::type* data);
so the compiler creates the function and the linker can find.
It's better to move the definitions in the header file - Why can templates only be implemented in the header file?.
The minimal code below gives me a compile error:
#include <iostream>
#include <functional>
using namespace std;
template<typename ActionType, typename... Cols>
void print_action(function<ActionType*(Cols..., ActionType)> action_factory)
{
}
int main(int argc, char *argv[])
{
print_action<string, uint8_t>(function<string*(uint8_t, string)>());
return 0;
}
The error is:
foo.cc: In function ‘int main(int, char**)’:
foo.cc:13:69: error: no matching function for call to ‘print_action(std::function<std::basic_string<char>*(unsigned char, std::basic_string<char>)>)’
print_action<string, uint8_t>(function<string*(uint8_t, string)>());
^
foo.cc:13:69: note: candidate is:
foo.cc:7:6: note: template<class ActionType, class ... Cols> void print_action(std::function<ActionType*(Cols ..., ActionType)>)
void print_action(function<ActionType*(Cols..., ActionType)> action_factory)
^
foo.cc:7:6: note: template argument deduction/substitution failed:
foo.cc:13:69: note: mismatched types ‘std::basic_string<char>’ and ‘unsigned char’
print_action<string, uint8_t>(function<string*(uint8_t, string)>());
^
foo.cc:13:69: note: ‘std::function<std::basic_string<char>*(unsigned char, std::basic_string<char>)>’ is not derived from ‘std::function<std::basic_string<char>*(Cols ..., std::basic_string<char>)>’
I also try to change the input parameter to a simple pointer function by below code:
#include <iostream>
#include <functional>
using namespace std;
template<typename ActionType, typename... Cols>
void print_action(ActionType*(*action_factory)(Cols..., ActionType))
{
}
string* foo_factory(uint8_t cols, string act)
{
}
int main(int argc, char *argv[])
{
print_action<string, uint8_t>(foo_factory);
return 0;
}
It gives me the same error. After some works my last guess is that it is a bug of g++ because if I change the variadic template parameter to a simple parameter no errors happen.
Am I right or I missed some syntax of c++?
I use g++-4.8.4 with c++11 flag(I checked it using clang-3.4 and g++-4.9.2).
EDIT:
If I change the code to this:
#include <iostream>
#include <functional>
using namespace std;
template<typename ActionType, typename... Cols>
struct Foo
{
Foo()
{}
void print_action(function<ActionType*(Cols..., ActionType)> action_factory)
{
}
};
int main(int argc, char *argv[])
{
Foo<string, uint8_t> f;
f.print_action(function<string*(uint8_t, string)>());
return 0;
}
I get no error. I don`t understand this behavior because in both situations I defined the template parameters explicitly and I did not expect any deduction, but It seems that compiler does some deduction when it is a template function but not when it is a member function of a template class.
The issue is that you have (Cols..., ActionType). One might think that the compiler should notice that Cols... should be all the arguments before the end so long as the end is the same as ActionType, but this is not how the language works.
A simple solution would to just deduce the entire argument list. Compilation will fail anyway if you happen to use the final argument as in a way the type doesn't support, and you could always add in a static_assert to ensure that the final parameter is the same as ActionType if you really wanted.
template<typename ActionType, typename... Cols>
void print_action(function<ActionType*(Cols...)> action_factory)
{
//Maybe with a static_assert like this
using LastArg = typename std::tuple_element<
sizeof...(Cols)-1, //number of args - 1
std::tuple<Cols...>
>::type;
static_assert(std::is_same<LastArg, ActionType>::value,
"The final argument must be the same type as ActionType");
}
Live Demo
Usually variadic templates are written thus
template<typename First, typename... Rest> class test;
The compiler matches the first argument and leaves the rest (empty or more) to variadic part. The behaviour when reversed is not as expected. Variadic template arguments are greedy, in that, all arguments are eaten-up by it, leaving none to the last.
Your example code compiles fine, when the order is reversed:
template<typename ActionType, typename... Cols>
void print_action(function<ActionType*(ActionType, Cols...)>) {
}
int main()
{
print_action(function<string*(string, uint8_t)>());
}
Live example.
There's a difference between argument type deduction and instantiation. Quote from C++ Templates: The Complete Guide:
The process of replacing template parameters by concrete types is called instantiation. It results in an instance of a template.
When a function template is instantiated, we get a function out of it; same for class/struct.
It seems that compiler does some deduction when it is a template function but not when it is a member function of a template class.
There is no type deduction or instantiation happening for the function call. It is not a function template, but just a function. The call is just another ordinary function call.
However, the struct is really a struct template and a struct is created out of the template, when an object was created. For this struct template instantiation
template<typename ActionType, typename... Cols>
struct Foo;
the order is correct (the variadic argument is the last) and so it works.
Platform specifics:
Fedora 21
g++ 4.9.2-6
Here's the error ....
$ g++ -c kabi-serial.cpp -lboost_serialization
kabi-serial.cpp: In function ‘void boost::serialization::kb_write_list()’:
kabi-serial.cpp:41:13: error: expected ‘;’ before ‘oa’
serialize oa(ofs);
kabi-serial.cpp:41:20: error: statement cannot resolve address of overloaded function
serialize oa(ofs);
^
kabi-serial.cpp:42:3: error: ‘oa’ was not declared in this scope
oa << ql;
And here's the kabi-serial.cpp source ...
#include <boost/serialization/vector.hpp>
#include <vector>
namespace boost {
namespace serialization {
class Cqnodelist
{
public:
friend class boost::serialization::access;
Cqnodelist(){}
std::vector<int>qnodelist;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & qnodelist;
}
};
void kb_write_list ()
{
Cqnodelist ql;
ofstream ofs("kabi-list.dat");
{
serialize oa(ofs);
oa << ql;
}
}
}
}
I based the source code on the simplest of the serialization examples, except using the serialization of the stl vector object.
I'm sure it's simple, but what am I missing?
To use ofstream you need to include <fstream>.
ofstream is in the namespace std: std::ofstream.
You don't need to put your code inside boost::serialization namespace (except case when you implement external to class serialize() function).
Adding serialize method implements way of loading and saving object attributes.
To actually store or load data you need to select storage — archive in Boost.Serialization terminology.
#include <boost/serialization/vector.hpp>
// include headers that implement a archive in simple text format
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <vector>
#include <fstream> // required for std::ofstream
class Cqnodelist
{
public:
friend class boost::serialization::access;
Cqnodelist(){}
std::vector<int>qnodelist;
template<class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & qnodelist;
}
};
void kb_write_list ()
{
Cqnodelist ql;
// fill object with data
ql.qnodelist.push_back(1);
ql.qnodelist.push_back(2);
ql.qnodelist.push_back(3);
// See http://www.boost.org/doc/libs/1_57_0/libs/serialization/doc/tutorial.html
// for reference
// save data to archive
{
// open file that will contain serialized data
std::ofstream ofs("kabi-list.dat");
// create archive on top of opened file
boost::archive::text_oarchive oa(ofs);
// write class instance to archive
oa << ql;
}
// to load object later open file, create input archive on top of opened
// file and load object state
{
Cqnodelist new_ql;
// create and open an archive for input
std::ifstream ifs("kabi-list.dat");
boost::archive::text_iarchive ia(ifs);
// read class state from archive
ia >> new_ql;
}
}
int main()
{
kb_write_list();
}