I am using std::deque to keep callback functions.
Everything works perfectly except removing a specific callback.
typedef std::function<void(void)> cb_Action;
std::deque<cb_Action> actionCallbacks;
I can Add items one by one or clear all of them without any problems.
But I cannot remove a specific callback from the deque variable.
actionCallbacks.erase ( std::remove(actionCallbacks.begin(), actionCallbacks.end(), callbackToRemove), actionCallbacks.end());
It gives compile time error:
binary '==': no operator found which takes a left-hand operand of type:'std::function<void(void)>' (or there is no acceptable conversion)
So, how can I remove a specific cb_Action?
If you deal with usual functions you can do something like this based on std::function::target:
void callback_1(void) {}
void callback_2(void) {}
actionCallbacks = {
std::function<void(void)>(callback_1),
std::function<void(void)>(callback_2),
std::function<void(void)>(callback_1)
};
actionCallbacks.erase(
std::remove_if(actionCallbacks.begin(), actionCallbacks.end(), [](cb_Action action) {
return (*action.target<void(*)(void)>() == callback_1);
}),
actionCallbacks.end()
);
Here all items with callback_1 inside are removed.
Related
I'm writing some kind of tool that extracts the interface definitions of C++ code.
In process of writing, I decided to restrict the parser to process only the code that was explicitly marked for processing, and I thought that C++ attributes are the best way to do it.
I'd prefer to add e.g. [[export]] annotations to entities I want to export, but I realised that libTooling is unable to see custom attributes without registering them in Clang code itself (I mean adding the attribute to tools/clang/include/clang/Basic/Attr.td).
Thus, my question is: is there a way to register the attribute without modifying that file (e.g. by registering the attribute programmatically or writing own Attr.td file)?
UPD: I'm using ASTMatchers library for source code analysis, so visitor-based approach probably does not work for me.
From what I can tell it is not possible to register custom attributes without directly modifying libtooling.
If you're willing to use pre-processor macros instead of attributes there is a workaround that I've done in the past. The basics are that we'll declare an empty macro, write a pre-processor callback to identify the location of the macro and store it in a queue, then in an AST visitor we'll visit records for either classes, methods, or variables, and check to see if preceeding the entity is our macro.
For the preprocessor you'll need to extend clang::PPCallbacks and implement the MacroExpands method.
void MyPreProcessorCallback::MacroExpands(const clang::Token& MacroNameTok, const clang::MacroDefinition&, const clang::SourceRange Range, const clang::MacroArgs* const Args)
{
// Macro is not named for some reason.
if(!MacroNameTok.isAnyIdentifier())
{ return; }
if(MacroNameTok.getIdentifierInfo()->getName() == "EXPORT")
{
// Save Range into a queue.
}
else
{
return;
}
// If you want arguments you can declare the macro to have varargs and loop
// through the tokens, you can have any syntax you want as they're raw tokens.
// /* Get the argument list for this macro, because it's a
// varargs function all arguments are stored in argument 0. */
// const ::clang::Token* token = Args->getUnexpArgument(0u);
// // All tokens for the argument are stored in sequence.
// for(; token->isNot(::clang::tok::eof); ++token)
// {
// }
}
Inside your RecursiveAstVisitor you can implement visitors that will pop off the top of the queue and check to see if the top macro is before in the translation unit. IIRC visitors of a type are all executed in order of declaration, so the queue should maintain the order. It is worth noting that all Decl's of a type are visited in order, so care has to be taken when distinguishing between function, variables, and classes.
bool MyAstVisitor::VisitFunctionDecl(::clang::FunctionDecl* const function)
{
if(::llvm::isa<::clang::CXXMethodDecl>(function))
{
// If you want to handle class member methods separately you
// can check here or implement `VisitCXXMethodDecl` and fast exit here.
}
if(ourExportTags.empty())
{
return true;
}
const ::clang::SourceLocation tagLoc = ourExportTags.front().getBegin();
const ::clang::SourceLocation declLoc = function->getBeginLoc();
if(getAstContext().getSourceManager().isBeforeInTranslationUnit(tagLoc, declLoc))
{
ourExportTags.pop_front();
// Handle export;
}
return true;
}
EDIT
I haven't used ASTMatchers before, but you could probably accomplish a similar result by writing a matcher, storing all of the declarations to a list, sorting based on location, and then comparing to the original export tag queue.
DeclarationMatcher matcher = functionDecl().bind("funcDecl");
class MyFuncMatcher : public clang::ast_matchers::MatchFinder::MatchCallback
{
public:
virtual void run(const clang::ast_matchers::MatchFinder::MatchResult& Result)
{
if(const FunctionDecl* func = Result.Nodes.getNodeAs<clang::FunctionDecl>("funcDecl"))
{
// Add to list for future processing
}
}
};
void joinTagsToDeclarations()
{
// Sort the declaration list
for(auto decl : myDeclList)
{
if(ourExportTags.empty())
{
break;
}
const ::clang::SourceLocation tagLoc = ourExportTags.front().getBegin();
const ::clang::SourceLocation declLoc = decl->getBeginLoc();
if(getAstContext().getSourceManager().isBeforeInTranslationUnit(tagLoc, declLoc))
{
ourExportTags.pop_front();
// Handle export;
}
}
}
I have a Server class that processes QJsonObject data and handles it according to a key set in the data.
At the moment, I use a big if-then-else statement to decide what to do like this:
const QString action = jsonObject.value(KEY_ACTION).toString();
if (action == SOME_ACTION) {
// do something
} else if (action == SOME_OTHER_ACTION) {
// do something else
}
and so on. Now, meanwhile, I have quite a lot of actions, and for each one, my server has to check all cases until it finds the correct one. I thus wondered if there was a nicer way to do this.
I thought about having the data processing in different functions and having a QHash with the respective function pointer to the respective function for each action like this:
In the constructor:
const QHash<QString, void(Server::*)(const QJsonObject &)> processFunctionsMap {
{ SOME_ACTION, &Server::processSomeAction },
{ SOME_OTHER_ACTION, &Server::processSomeOtherAction }
}
And the respective functions:
void Server::processSomeAction(const QJsonObject &data)
{
...
}
and then to invoke the matching function:
if (! processFunctionsMap.contains(action)) {
// Catch this case
}
(this->*processFunctionsMap.value(action))(jsonObject);
This seems to work, but I'm not a C++ pro, so my question is if this is the correct way to do it.
Your approach is reasonable, but you've changed the no-matches scenario from executing an else block (potentially doing nothing at all) to instant undefined behavior.
You need to separate the hash lookup from the call so you can insert a check for successful lookup in between. With C++ standard collections (std::map which is a red-black tree, std::unordered_map which is a hashtable), that'd be a call to find(key) which returns an iterator... you compare it to map.end() and make very sure not to dereference if they are equal. QHash, or any other non-standard hashtable, will surely provide something similar.
Understanding what QHash does when key not found
How can I calculate a hash/checksum/fingerprint of an object in c++?
Requirements:
The function must be 'injective'(*). In other words, there should be no two different input objects, that return the same hash/checksum/fingerprint.
Background:
I am trying to come up with a simple pattern for checking whether or not an entity object has been changed since it was constructed. (In order to know which objects need to be updated in the database).
Note that I specifically do not want to mark the object as changed in my setters or anywhere else.
I am considering the following pattern: In short, every entity object that should be persisted, has a member function "bool is_changed()". Changed, in this context, means changed since the objects' constructor was called.
Note: My motivation for all this is to avoid the boilerplate code that comes with marking objects as clean/dirty or doing a member by member comparison. In other words, reduce risk of human error.
(Warning: psudo c++ code ahead. I have not tried compiling it).
class Foo {
private:
std::string my_string;
// Assume the "fingerprint" is of type long.
long original_fingerprint;
long current_fingerprint()
{
// *** Suggestions on which algorithm to use here? ***
}
public:
Foo(const std::string& my_string) :
my_string(my_string)
{
original_fingerprint = current_fingerprint();
}
bool is_changed() const
{
// If new calculation of fingerprint is different from the one
// calculated in the constructor, then the object has
// been changed in some way.
return current_fingerprint() != original_fingerprint;
}
void set_my_string(const std::string& new_string)
{
my_string = new_string;
}
}
void client_code()
{
auto foo = Foo("Initial string");
// should now return **false** because
// the object has not yet been changed:
foo.is_changed();
foo.set_my_string("Changed string");
// should now return **true** because
// the object has been changed:
foo.is_changed();
}
(*) In practice, not necessarily in theory (like uuids are not unique in theory).
You can use the CRC32 algorithm from Boost. Feed it with the memory locations of the data you want to checksum. You could use a hash for this, but hashes are cryptographic functions intended to guard against intentional data corruption and are slower. A CRC performs better.
For this example, I've added another data member to Foo:
int my_integer;
And this is how you would checksum both my_string and my_integer:
#include <boost/crc.hpp>
// ...
long current_fingerprint()
{
boost::crc_32_type crc32;
crc32.process_bytes(my_string.data(), my_string.length());
crc32.process_bytes(&my_integer, sizeof(my_integer));
return crc32.checksum();
}
However, now we're left with the issue of two objects having the same fingerprint if my_string and my_integer are equal. To fix this, we should include the address of the object in the CRC, since C++ guarantees that different objects will have different addresses.
One would think we can use:
process_bytes(&this, sizeof(this));
to do it, but we can't since this is an rvalue and thus we can't take its address. So we need to store the address in a variable instead:
long current_fingerprint()
{
boost::crc_32_type crc32;
void* this_ptr = this;
crc32.process_bytes(&this_ptr, sizeof(this_ptr));
crc32.process_bytes(my_string.data(), my_string.length());
crc32.process_bytes(&my_integer, sizeof(my_integer));
return crc32.checksum();
}
Such a function does not exist, at least not in the context that you are requesting.
The STL provides hash functions for basic types (std::hash), and you could use these to implement a hash function for your objects using any reasonable hashing algorithm.
However, you seem to be looking for an injective function, which causes a problem. Essentially, to have an injective function, it would be necessary to have an output of size greater or equal to that of the object you are considering, since otherwise (from the pigeon hole principle) there would be two inputs that give the same output. Given that, the most sensible option would be to just do a straight-up comparison of the object to some sort of reference object.
I don't have a lot of experience writing C++ and I'm struggling with an issue. The code below is kind of scraped together from snippets. I am writing a class and I want it to have an attribute map of string keys and function values:
std::map< std::string, std::function<bool(std::string)> > selection_filters;
I then want to add pairs as follows:
auto some_func = [] (std::string value) { return value == "some_val"; };
selection_filters["some_key"] = some_func;
//or
selection_filters.insert(std::make_pair("some_key", some_func));
Such that I can:
if ( selection_filters["some_key"]("function param") == true ) {
//etc..
}
This compiles, but throws an error at runtime:
terminating with uncaught exception of type std::__1::bad_function_call: std::exception
I suspect it may have something to do with a discrepancy between std::function<bool(std::string)> in the map definition, and the use of the lambda function [] (std::string value) { ... };
I would very much like to preserve the use of lambda functions and the possibility to access the functions through the subscript operators on the map (map['some_key'](..)) but my knowledge of C++ is not good enough to come up with a solution.
Can someone please point out the error I'm making (and why it is thrown; I want to learn) and provide suggestions for improvement?
See What causes std::bad_function_call?
Missing or empty function. Be sure to check that "some_key" exists in the map before you call the function,
if(selection_filters.find("some_key") != selection_filters.end())
or at least check that the function has a valid target:
if(selection_filters["some_key"])
When you use the [] operator on an std::map, it will insert a default constructed object (or zero) if it is not already in the map. This can (and will) cause lots of invalid entries for keys that you have not explicitly set.
I was porting some legacy code to VS 2015 when this compiler error halted the build:
error C3867: 'OptDlg::GetFullModel': non-standard syntax; use '&' to create a pointer to member
Going to the corresponding file and line, I saw this:
Manager mgr = GetDocument()->GetManager();
OptDlg dlg;
...
mgr->SetFullModel(dlg.GetFullModel);
if ( dlg.GetFullModel )
mgr->SetSymm(...
GetFullModeland SetFullModel are the getter/setter pair for a member variable in two different classes:
class Manager {
...
bool GetFullModel() { return m_bFullModel; }
void SetFullModel(bool bFlag) { m_bFullModel = bFlag; }
....
};
class OptDlg {
...
void GetFullModel() { return m_bFullModel; }
void SetFullModel(bool bValue) { m_bFullModel = bValue; if ( bValue ) m_bInside = 0;}
Yep, something's wrong. Was dlg.GetFullModel supposed to be a pointer to a member function? I thought those use the class name, not an instance. Not to mention what that would mean for execution semantics...
C++ is still relatively new to me, so I tried Google. It had a lot on function pointers, but they all looked different from what I had:
&OptDlg::GetFullModel // Standard-compliant
vs
OptDlg::GetFullModel // The "normal" way to mess up getting a pointer to member, it seems
vs
dlg.GetFullModel // ?
Is dlg.GetFullModel just another way of getting a pointer to member function? If not, what is the "standard C++ version", if there is one? Is this just another one of those VS 6 "extensions"?
&OptDlg::GetFullModel // Standard-compliant
If your parameter types were supposed to be taking member functions, that's what you'd use. But they take booleans. It looks like you're just missing parentheses on your function calls, and it should be:
mgr->SetFullModel(dlg.GetFullModel());
if (dlg.GetFullModel())
mgr->SetSymm(...
Probably someone was ignoring warnings (or didn't have them on) and hence a pointer value (being produced through whatever shady means) was always being interpreted as non-NULL, hence boolean true.
Is this just another one of those VS 6 "extensions"?
It would appear to be the case, although this comment is the only documented evidence I can find it was an intentional/advertised "feature". Don't see any formal announcement of it being added or taken out.
It strongly looks to me like someone mis-typed dlg.GetFullModel() (which would call the function), not that they were trying to get a member function pointer.
Presumably the legacy compiler let it slide, taking the address of the function without using & and converting the non-null function pointer to bool (with value true) to pass into the set function.