C++ Internal compiler error working with native events - visual-studio

__event T e(args);
On line 9, VS gives me green squigglies under 'e' with the warning: Function definition for 'e' not found.
On compile/build, it throws the C1001 internal error occurred in the compiler (line 9 again).
I've tried renaming the variable, tried removing the template and just working with normal types, tried making it public.
If anyone can help it would be greatly appreciated, thank you.
(Whole code probably not necessary but just to give an idea what I'm going for)
#include <cstdarg>
#include <functional>
#include <iostream>
template <typename T, typename ... args>
[event_source(native)]
class Action {
private:
__event T e(args);
public:
~Action() {
__unhook(this);
};
void operator +=(std::function<T(args...)> f) {
__hook(e, this, &f);
}
void operator -=(std::function<T(args...)> f) {
__unhook(e, this, &f);
}
void operator()(args...) {
__raise e(args);
}
};
void print(const char* s) {
std::cout << s << std::endl;
}
int main() {
Action<void, const char*> printAction;
printAction += print;
printAction("Print a string.");
printAction -= print;
}

Related

Trying to implement Observer Patterns and got Segmentation Fault (pls help) c++

I'm trying to learn c++ so, I try to implement the observer patterns from the book Game Progamming Patterns but I'm always getting Segmentation Fault.
Searching arround I saw that Segmentation fault happens when a program try to access a non allocated memory. So I tried hard to fix it, but I can't. Someone can help me?
Here is my code:
Observer.h
#ifndef OBSERVER_H
#define OBSERVER_H
#include "EntityAndEvent.h"
#include "Subjects.h"
class Observer
{
private:
Observer* next_;
public:
Observer()
: next_(nullptr)
{}
virtual void onNotify(const Entity& entity, Event::Type event) = 0;
// Other stuff...
friend class Subjects;
};
#endif
Achievements.cpp
#ifndef ACHIEVEMENTS_CPP
#define ACHIEVEMENTS_CPP
#include "Observer.h"
#include <vector>
class Achievements : public Observer
{
public:
enum Type{
FELL_OFF,
AWAKE_ON
};
private:
std::vector<Type> done{};
public:
virtual void onNotify(const Entity&, Event::Type);
void unlock(Achievements::Type);
void printDone();
};
void Achievements::onNotify(const Entity& entity, const Event::Type event)
{
switch (event)
{
case Event::Type::ENTITY_FELL:
if(entity.isHero())
unlock(Achievements::Type::FELL_OFF);
break;
case Event::Type::ENTITY_AWAKE:
if(entity.isHero())
unlock(Achievements::Type::AWAKE_ON);
break;
default:
break;
}
};
void Achievements::unlock(Achievements::Type achiev)
{
done.push_back(achiev);
}
void Achievements::printDone()
{
// assert(done.size());
for(size_t i{0}; i < done.size(); i++)
{
std::cout << done[i] << "\n";
}
};
EntityAndEvent.cpp (i create this just to work with observer and subjects)
#ifndef ENTITY_AND_EVENT_H
#define ENTITY_AND_EVENT_H
class Entity
{
public:
inline const bool isHero() const {return true;}
};
class Event
{
public:
enum Type{
ENTITY_FELL,
ENTITY_AWAKE
};
};
#endif
Subjects.h
#ifndef SUBJECT_H
#define SUBJECT_H
#include "Observer.h"
#include <vector>
class Observer;
class Subjects
{
private:
// when implements this, prefer to use linked list or another optimized algorithms
Observer* head_{};
protected:
void notify(const Entity& Entity, Event::Type event);
public:
Subjects() : head_(NULL)
{};
~Subjects() {}
void addObserver(Observer* observer);
// const int getNumObs() const {return num_obs_;}
};
#endif
Subjects.cpp
#include "Subjects.h"
#include <cassert>
void Subjects::notify(const Entity& entity, Event::Type event)
{
Observer* observer = head_;
while (observer != NULL)
{
observer->onNotify(entity, event);
observer = observer->next_;
};
};
void Subjects::addObserver(Observer* observer)
{
if (head_ != nullptr)
observer->next_ = head_;
head_ = observer;
};
Physics.cpp (i create this just to populates the subject)
#ifndef PHYSICS_H
#define PHYSICS_H
#include "Subjects.h"
#include "EntityAndEvent.h"
class Physics: public Subjects
{
private:
public:
void update(const Entity& entity)
{
if (entity.isHero())
{
notify(entity, Event::Type::ENTITY_AWAKE);
};
};
};
#endif
main.cpp
#include "Observer.h"
#include "Achievements.h"
#include "Achievements.cpp"
#include "EntityAndEvent.h"
#include "Physics.h"
#include "Subjects.h"
#include "Subjects.cpp"
int main()
{
Physics *p{};
Entity e{};
Achievements *achiev{};
p->addObserver(achiev);
p->update(e);
return 0;
}
With Physics *p{}; you are declaring a pointer, but it currently does not point to a valid object (it is being initialized as nullptr here). Therefore, calling p->addObserver results in a segmentation fault. You should be able to confirm this by running the program in a debugger.
Why are you using a pointer here? Change Physics *p{}; to Physics p{};.
Disclaimer: Since your code is definitely not a minimum example I didn't look into the whole code or even tried to compile it. I'm only posting an answer because there is a clear error in the main function (use of an invalid pointer) that results in a segmentation fault.
first, tks for the reply. #darcamo that works. I dont know why it was declared as pointer.
I fixed that, so if anyone else have the same doubt check below:
main.cpp
#include "Observer.h"
#include "Achievements.h"
#include "EntityAndEvent.h"
#include "Physics.h"
#include "Subjects.h"
int main()
{
Physics p{};
Entity e{};
Achievements achiev{};
Observer* ptr_achiev{&achiev};
p.addObserver(ptr_achiev);
p.update(e);
return 0;
}

Error C2679 binary '<<': no operator found which takes a right-hand operand of type 'T' (or there is no acceptable conversion)

I'm having problems with my friend function within my template class. For some reason it doesn't like the fact that I'm trying to use a variable that is type T in an operator overloading friend function.
#include <iostream>
#include <fstream>
#include <string>
template <typename T>
class LL
{
struct Node
{
T mData;
Node *mNext;
Node();
Node(T data);
};
private:
Node *mHead, *mTail;
int mCount;
public:
LL();
~LL();
bool insert(T data);
bool isExist(T data);
bool remove(T data);
void showLinkedList();
void clear();
int getCount() const;
bool isEmpty();
friend std::ofstream& operator<<(std::ofstream& output, const LL& obj)
{
Node* tmp;
if (obj.mHead != NULL)
{
tmp = obj.mHead;
while (tmp != NULL)
{
output << tmp->mData << std::endl; // "tmp->mData is causing the error
tmp = tmp->mNext;
}
}
return output;
}
};
This is a linked list class, and I need the friend function operator overload to basically allow me to output any particular list of objects onto a text file. I hope someone can help me out.

Perfect forward variadic arguments to lambda

Somehow I need to implement lazy evaluation with c++ variadic lambda. I am not quite sure whether the following code works correctly.
template <typename... ArgsT>
auto lazy_pack(ArgsT&& ... args) {
auto T = [&](bool condition) {
if(condition == false) return;
Foo v(std::forward<ArgsT>(args)...);
v.do_work();
};
return T;
}
The question is, how do I capture a given argument list and perfectly forward them to another templated object? The above example compiles but I am worried about if any dangling reference might happen. Another way is to capture arguments through copy and them and pass to the object:
template <typename... ArgsT>
auto lazy_pack(ArgsT&& ... args) {
auto T = [=](bool condition) {
if(condition == false) return;
Foo v(args...);
v.do_work();
};
return T;
}
I'm not sure I got what you are looking for, but maybe the following code can help you:
#include <tuple>
#include <functional>
#include <cstddef>
#include <utility>
#include <iostream>
struct Foo {
Foo(int v, const char *s): val{v}, str{s} { }
void do_work() { std::cout << val << " " << str << std::endl; }
int val;
const char *str;
};
template<std::size_t... I, typename... ArgsT>
auto lazy_pack(std::index_sequence<I...>, ArgsT&&... args) {
return [tup{std::forward_as_tuple(std::forward<ArgsT>(args)...)}](bool condition) {
if(condition == false) return;
Foo v(std::get<I>(tup)...);
v.do_work();
};
}
template<typename... ArgsT>
auto lazy_pack(ArgsT&& ... args) {
return lazy_pack(std::make_index_sequence<sizeof...(ArgsT)>(), std::forward<ArgsT>(args)...);
}
int main() {
auto l = lazy_pack(42, "bar");
l(false);
l(true);
}
You need at least one more helper function to be able to unpack later the parameters forwarded to the first one.

What is the best way to pass callback function to std::map?

I was trying to work on the below code but the program crashes:
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef void (*callBackMethod)(string);
class CTest
{
private:
map<string, callBackMethod> mapMethod;
void testMethod(string msg)
{
cout << msg << endl;
}
public:
CTest()
{
addFunction("AA", (callBackMethod) &CTest::testMethod);
}
void addFunction(string funName, callBackMethod methodName)
{
mapMethod[funName] = methodName;
}
callBackMethod getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
return 0;
}
I have a requirement where I need to pass private methods to a map. The program compiles with warning:
converting from 'void (CTest::*)(std::__cxx11::string) {aka void (CTest::*)(std::__cxx11::basic_string<char>)}' to 'callBackMethod {aka void (*)(std::__cxx11::basic_string<char>)}'
and when I execute this, it crashes.
When I move the callback method outside of the class it works. My requirement is to make the program flow this was (hide the methods from external call which needs to be added to a map).
Looking forward to your comments.
If you need to point to both CTest member functions and free functions, then you can use std::function<void(std::string)>.
#include <iostream>
#include <string>
#include <map>
#include <functional>
using namespace std;
using callBackFunction = std::function<void(string)>;
void testFunction(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
class CTest
{
private:
map<string, callBackFunction> mapMethod;
void testMethod(string msg)
{
cout << "[" << __PRETTY_FUNCTION__ << "] " << msg << endl;
}
public:
CTest()
{
addFreeFunction("AA", testFunction);
addMemberFunction("BB", &CTest::testMethod);
}
void addMemberFunction(string funName, void(CTest::*methodName)(string))
{
using std::placeholders::_1;
mapMethod[funName] = std::bind(methodName, this, _1);
}
void addFreeFunction(string funName, void(*methodName)(string))
{
mapMethod[funName] = methodName;
}
callBackFunction getMethod(string funName)
{
auto fun = mapMethod.find(funName);
if(fun == mapMethod.end()) { return nullptr; }
return fun->second;
}
void runFunction(string funName)
{
getMethod(funName)("test");
}
};
int main()
{
CTest test;
test.runFunction("AA");
test.runFunction("BB");
return 0;
}
Notice that CTest must insert elements into the map in a different way depending on what type of function you are passing, since for member functions you must provide the object for which it is to be invoked, this in this example. This is achived by using std::bind.
Since you want to use member variables you need to specify the signature differently in your typedef:
In C++ Builder the following can be done:
typedef void(__closure *callBackMethod)(string);
If you do that, I do suggest that you keep a smart pointer to the object that the member belongs to so that you can check if the object is still valid before calling the function otherwise it will crash the application.
The __closure keyword is a C++ Builder extension to work around the requirement to use fully qualified member names source
To handle both global and member functions we have the following:
typedef void(__closure *callBackMethodMember)(string);
typedef void (*callBackMethodGlobal)(string);
/* And then on 2 overloaded functions */
void addFunction(string funName, callBackMethodMember methodName) {}
void addFunction(string funName, callBackMethodGlobal methodName) {}

performing static cast from a non template base class to a templated derived class which has variadic template parameter (c++)

I wanted to store a vector of function pointers, each taking different no. of arguments in a class "Store". So, wrote a templated class "Func" that would store the function as a std::function and its arguments in a tuple.
I derived this "Func" class from a non-template base class "IFunc", so that i can store a vector of pointers to this base class in the class "Store".
template<typename... Args>
class Func : public IFunc
{
public:
std::function<void (Args...)> f;
std::tuple<Args...> args;
template <typename F,typename... Ar>
Func(F&& func,Ar&&... arg): f(std::forward<F>(func)),args(std::make_tuple(std::forward<Ar>(arg)...))
{
}
virtual ~NonMemfun()
{
}
//other methods to unpack the tuple and call the function
};
The IFunc class:
class IFunc
{
public:
Ifunc(){}
virtual ~Ifunc(){}
};
The Store class:
class Store
{
std::vector<Ifunc*> funcs;
public:
template<typename... Args,typename... Args2>
void registerfunc(std::string name,int runs,void(*f)(Args...),Args2&&... arg)
{
Func<Args2...>* sample = new Func<Args2...>(f,arg...);
Ifunc* fp = sample;
funcs.push_back(fp);
}
};
I want to iterate through the vector and call each function. To do that i need to do a static cast like this:
Func<>* der = static_cast<Func<>*>(funcs[0]);
When i try to do this, the cast doesn't happen properly. I cannot specify the template paramenters(variadics) since this class(Store) is not aware of them.
I am totally stuck at this place. Something is wrong with my design i guess. Can someone please suggest me a better way to do this. Thank you.
Rather than trying to do a cast from IFunc to Func<>, you should make a pure virtual function, Apply() in IFunc, which Func<> defines as apply(f, args...);. As you iterate over the vector of IFunc pointers, simply call IFunc->Apply(), which will dispatch to the Func<>::Apply() and do the actual apply.
I'm not much of a C++ programmer, but I think you may find this useful.
I'm sure you know that templates are a compile time thing in C++ so your functions need to be known at build time.
With that said, if you do know your functions and you just want to map them to say a string command and then dynamically bind arguments from something like a stream then this code should help you. It is actually able to use a dynamic_cast to retrieve the command from the map.
this snippet is from a school project I did a while back that had a similar goal:
#include <map>
#include <string>
#include <sstream>
#include <tuple>
using namespace std;
class Shell {
class Command {
public:
virtual ~Command() {};
virtual void executeWithArgStream(Shell*, istream& s)=0;
};
template <typename... ArgTypes>
class ShellCommand : public Command {
private:
// FIXME: its probably more apropriate for FuncType to return an int for exit code...
typedef function<void(Shell*, ArgTypes...)> FuncType;
FuncType _f;
tuple<ArgTypes...> args;
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N - 1, N - 1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { typedef seq<Is...> type; };
template<size_t I = 0, class ...P>
typename std::enable_if<I == sizeof...(P)>::type
// template for functions with no arguments
parseArgs(istream& is, std::tuple<P...> &) {}
template<size_t I = 0, class ...P>
typename std::enable_if<I < sizeof...(P)>::type
parseArgs(istream& is, std::tuple<P...> & parts) {
// this is the magic bit that takes a tuple of pointers (representing the command arguments)
// created at compile time and creates new instances of each argument type and populates it from
// the given input stream :D
auto& part = std::get<I>(args);
// hmmm should we delete or recycle...
delete part;
part = new typeof(*part);
is >> *part;
parseArgs<I + 1>(is, parts);
}
template<int ...S>
void callFunc(Shell* shell, seq<S...>) {
_f(shell, get<S>(args) ...);
}
public:
static constexpr size_t numArgs = sizeof...(ArgTypes);
ShellCommand(FuncType f) : _f(f) {};
void operator()(Shell* shell, ArgTypes... args) {
_f(shell, args...);
};
void executeWithArgStream(Shell* shell, istream& s)
{
parseArgs(s, args);
callFunc(shell, typename gen_seq<sizeof...(ArgTypes)>::type());
};
};
private:
typedef shared_ptr<Command> CommandPtr;
typedef map<string, CommandPtr> FMap;
FMap _cmdMap;
ostream& _out;
istream& _in;
public:
Shell(istream& is = cin, ostream& os = cout)
: _out(os), _in(is)
{
// populate
_cmdMap.insert(pair<string, CommandPtr>("chdir", make_shared<ShellCommand<string*>>(&Shell::chdir)));
_cmdMap.insert(pair<string, CommandPtr>("list", make_shared<ShellCommand<>>(&Shell::list)));
_cmdMap.insert(pair<string, CommandPtr>("count", make_shared<ShellCommand<>>(&Shell::count)));
};
int run();
// FIXME: its probably more apropriate for execute to return an int for exit code...
template <typename... ArgTypes>
void execute(string& command, ArgTypes... args);
void executeWithArgStream(string& command, istream& istr);
// shell commands:
// any command parameters must be done as a pointer!
// the magic that parses string arguments into real types depends on it!
void list() {
list command
};
void chdir(string* dir) {
// chdir command
};
void count() {
// count command
};
};
template <typename... ArgTypes>
void Shell::execute(string& command, ArgTypes... args)
{
typedef ShellCommand<ArgTypes...> CommandType;
CommandType* c = dynamic_cast<CommandType*>(_cmdMap[command].get());
// TODO: neeed to diferentiate between invalid commands and some kind of dynamic_cast failure
if (c) {
(*c)(this, args...);
} else {
// dynamic cast failure
throw runtime_error("Broken Implementation for:" + command);
}
}
void Shell::executeWithArgStream(string& command, istream& istr)
{
Command* c = _cmdMap[command].get();
if (c) {
c->executeWithArgStream(this, istr);
} else {
throw runtime_error("Invalid Shell Command: " + command);
}
}
int Shell::run()
{
do {
string cmd, argString;
_out << _currentDir->name() << "> ";
_in.clear();
_in >> cmd;
if (cmd == "q") {
return 0;
}
if (_in.peek() == ' ')
_in.ignore(1, ' ');
getline(cin, argString);
if (_cmdMap[cmd]) {
try {
if (argString.length()) {
istringstream s(argString);
executeWithArgStream(cmd, s);
} else {
execute(cmd);
}
} catch (runtime_error& e) {
_out << e.what() << endl;
}
} else {
_out << "unrecognized command: " << cmd << endl;
}
} while (true);
}
int main(int argc, const char * argv[])
{
// start the interactive "shell"
Shell shell();
return shell.run();
}

Resources