Problems implementing ToString specialization for unit testing c++ - c++

Right now i'm busy writing an event based queue. I wanted to do some unit testing but i'm running into an error. In Microsoft Visual Studio, when making a unit test project, you have to implement this function for each type you do an assert on:
namespace Microsoft
{
namespace VisualStudio
{
namespace CppUnitTestFramework
{
template<> static std::wstring ToString<T>>(const class T& t)
{
//code goes here
}
}
}
}
the problem is that the queue is not changing the object that was passed into it. because of this i wanted to write a unit test that verified that the object pointed to in the queue, was the same address as the object outside of the queue. I wrote the test as follows:
TEST_METHOD(REGISTERED_PROCESSORS_HAVE_ACCURATE_ADDRESSES_IN_QUEUE_MANAGER)
{
QueueProcessor queue;
ActionProcessor processor;
processor.loadFromJson({ {actionProcessorProperties::QUEUE_NAME, "alpha"} });
queue.registerProcessor(&processor);
Assert::AreEqual(&processor, queue.processors["alpha"][0]);
}
i then get this error:
Test writer must define specialization of ToString<Q* q> for your class class std::basic_string<wchar_t,struct std::char_traits<wchar_t>,class std::allocator<wchar_t> > __cdecl Microsoft::VisualStudio::CppUnitTestFramework::ToString<class ActionProcessor>(class ActionProcessor *).
so how do I implement ToString on a pointer? when I try putting the data type in the compiler complains. Also how do I then display the pointer as a string value?
thanks for the help.
edit:
i found the unit test works fine if you convert the pointers to uintptr_t. However the type conversion mid assert kinda messes up the readability of the code. Is there a cleaner solution?
TEST_METHOD(REGISTERED_PROCESSORS_HAVE_ACCURATE_ADDRESSES_IN_QUEUE_MANAGER)
{
QueueProcessor queue;
ActionProcessor processor;
processor.loadFromJson({ {actionProcessorProperties::QUEUE_NAME, "alpha"} });
queue.registerProcessor(&processor);
Assert::AreEqual(reinterpret_cast<uintptr_t> (&processor),
reinterpret_cast<uintptr_t>(queue.processors["alpha"][0]));
}

Since nobody seems to be answering this, I'm going to mark my edit as correct. Perhaps the way to do it is by converting the pointers to uintptr_t types. The code below fixes the issue:
TEST_METHOD(REGISTERED_PROCESSORS_HAVE_ACCURATE_ADDRESSES_IN_QUEUE_MANAGER)
{
QueueProcessor queue;
ActionProcessor processor;
processor.loadFromJson({ {actionProcessorProperties::QUEUE_NAME, "alpha"} });
queue.registerProcessor(&processor);
Assert::AreEqual(reinterpret_cast<uintptr_t> (&processor),
reinterpret_cast<uintptr_t>(queue.processors["alpha"][0]));
}

Related

Access a Class Object inside a static restbed handler

I am currently getting familiar with restbed for a project but ran into a problem right at the start. I admit that this might be something very trivial but still a problem for me at the time.
Restbed service requires a const callback function
void set_method_handler( const std::string& method, const std::function< void ( const std::shared_ptr< Session > ) >& callback );
The thing is that I wand to create a REST service to GET some data from a class object.
HEADER
std::shared_ptr<restbed::Resource> REST_get_test;
static void get_test_handler(const std::shared_ptr< restbed::Session > session );
CONSTRUCTOR
REST_get_test = std::make_shared< restbed::Resource >( );
REST_get_test->set_path( "/test" );
REST_get_test->set_method_handler( "GET", get_test_handler);
The handler I call is supposed to iterate through a structure (Code is not finished, but enough to illustrate the problem)
void c_module_home::get_test_handler( const std::shared_ptr< restbed::Session > session )
{
QJsonObject status;
for (auto iter = cortexDrones.begin(); iter!= cortexDrones.end(); ++iter){
}
session->close( restbed::OK, "Hello, World!", { { "Content-Length", "13" }, { "Connection", "close" } } );
}
As expected I get a:
error: invalid use of member 'project::c_module_home::cortexDrones' in static member function
Does anyone have a suggestion how to handle that? Thanks a lot!!
Long story short... it's not a very trivial problem; at least the answer behind why it's not working as expected.
get_test_handler is a static member function in a class and it cannot access non-static properties.
If get_test_handler is a non-static member function in a class it cannot function as a callback, because a member function pointer is not the same as a "normal" function pointer.
Member functions expect the this pointer to be passed as first parameter. This is done by the compiler automatically; meaning that the function signatures do not match.
In my first attempts at mainly the same thing (using restbed), on of the first thoughts was to make the handler static, but that forces you to have anything else you might access from the handler be static as well. This is not a solution in my opinion.
The solution I found after some struggling with the same problem is to wrap the handler in a lambda function; at least if you're using C++11 or greater.
Short example based on your code:
resource->set_method_handler("GET",
[&](const std::shared_ptr<restbed::Session> session) {
get_test_handler(session);
});
Main point here is not to get the idea that a lambda is a std::function; it's an unspecified type which can be assigned to a std::function (of course the type has to match).
You can find more details in the following links:
https://en.cppreference.com/w/cpp/language/lambda
https://shaharmike.com/cpp/lambdas-and-functions/
UPDATE:
I found this link which in my opinion describes best C++ lambdas: https://www.cprogramming.com/c++11/c++11-lambda-closures.html and it's a way easier read compared to the cppreference.com one.
I know this is already answered but if you do not want to use lambdas you can use std::bind.
Short example based on your code:
resource->set_method_handler("GET",std::bind(&c_module_home::get_test_handler, this, _1));

c++ Compiler could not generate operator= for class

This code:
struct TToken
{
UnicodeString &DBIDs;
std::vector<TToken> T;
TToken(UnicodeString &DI) : DBIDs(DI) {}
void Append(void) {T.push_back(TToken(DBIDs));}
};
UnicodeString DI="25,40,55";
TToken T(DI);
if (T.DBIDs==DI) // if I comment out this comparison it works fine
....
generates the above compiler error (I'm using C++Builder 10.1 Berlin).
If I change the UnicodeString reference to a pointer, it all works as expected. Does anyone know why the reference generates the error?
By the way, is there an easier way of making DBIDs available to every created vector element instead of passing a pointer/reference all the way down the line? A static member is no good, and I did look at template expressions, but couldn't get an acceptable answer.

Bad practice to call static function from external file via function pointer?

Consider the following code:
file_1.hpp:
typedef void (*func_ptr)(void);
func_ptr file1_get_function(void);
file1.cpp:
// file_1.cpp
#include "file_1.hpp"
static void some_func(void)
{
do_stuff();
}
func_ptr file1_get_function(void)
{
return some_func;
}
file2.cpp
#include "file1.hpp"
void file2_func(void)
{
func_ptr function_pointer_to_file1 = file1_get_function();
function_pointer_to_file1();
}
While I believe the above example is technically possible - to call a function with internal linkage only via a function pointer, is it bad practice to do so? Could there be some funky compiler optimizations that take place (auto inline, for instance) that would make this situation problematic?
There's no problem, this is fine. In fact , IMHO, it is a good practice which lets your function be called without polluting the space of externally visible symbols.
It would also be appropriate to use this technique in the context of a function lookup table, e.g. a calculator which passes in a string representing an operator name, and expects back a function pointer to the function for doing that operation.
The compiler/linker isn't allowed to make optimizations which break correct code and this is correct code.
Historical note: back in C89, externally visible symbols had to be unique on the first 6 characters; this was relaxed in C99 and also commonly by compiler extension.
In order for this to work, you have to expose some portion of it as external and that's the clue most compilers will need.
Is there a chance that there's a broken compiler out there that will make mincemeat of this strange practice because they didn't foresee someone doing it? I can't answer that.
I can only think of false reasons to want to do this though: Finger print hiding, which fails because you have to expose it in the function pointer decl, unless you are planning to cast your way around things, in which case the question is "how badly is this going to hurt".
The other reason would be facading callbacks - you have some super-sensitive static local function in module m and you now want to expose the functionality in another module for callback purposes, but you want to audit that so you want a facade:
static void voodoo_function() {
}
fnptr get_voodoo_function(const char* file, int line) {
// you tagged the question as C++, so C++ io it is.
std::cout << "requested voodoo function from " << file << ":" << line << "\n";
return voodoo_function;
}
...
// question tagged as c++, so I'm using c++ syntax
auto* fn = get_voodoo_function(__FILE__, __LINE__);
but that's not really helping much, you really want a wrapper around execution of the function.
At the end of the day, there is a much simpler way to expose a function pointer. Provide an accessor function.
static void voodoo_function() {}
void do_voodoo_function() {
// provide external access to voodoo
voodoo_function();
}
Because here you provide the compiler with an optimization opportunity - when you link, if you specify whole program optimization, it can detect that this is a facade that it can eliminate, because you let it worry about function pointers.
But is there a really compelling reason not just to remove the static from infront of voodoo_function other than not exposing the internal name for it? And if so, why is the internal name so precious that you would go to these lengths to hide that?
static void ban_account_if_user_is_ugly() {
...;
}
fnptr do_that_thing() {
ban_account_if_user_is_ugly();
}
vs
void do_that_thing() { // ban account if user is ugly
...
}
--- EDIT ---
Conversion. Your function pointer is int(*)(int) but your static function is unsigned int(*)(unsigned int) and you don't want to have to cast it.
Again: Just providing a facade function would solve the problem, and it will transform into a function pointer later. Converting it to a function pointer by hand can only be a stumbling block for the compiler's whole program optimization.
But if you're casting, lets consider this:
// v1
fnptr get_fn_ptr() {
// brute force cast because otherwise it's 'hassle'
return (fnptr)(static_fn);
}
int facade_fn(int i) {
auto ui = static_cast<unsigned int>(i);
auto result = static_fn(ui);
return static_cast<int>(result);
}
Ok unsigned to signed, not a big deal. And then someone comes along and changes what fnptr needs to be to void(int, float);. One of the above becomes a weird runtime crash and one becomes a compile error.

Anonymous Functions, "Parse Issue: Expected Expression"

I'm getting the titular error, but I can't for the life of me figure out how to resolve it. I've scoured the internet a fair bit, but for the most part I can't find anything that pertains directly to, or solves, the problem I'm having, and all the information I read about anonymous classes, seems to agree with the code I wrote.
The essence of what I'm trying to do is; I have a struct, and I want that struct to contain a function pointer. What I'm having trouble with is when I define an instance of the struct, I'm trying to create and pass an anonymous function to the struct. But it's giving me a compile error.
Anyways, here are the details of the actual problem, the error occurs on this line,
[&](int x) { this->moveLeft(); };
It says "Parse Issue: Expected expression" and points to the ']'
of the following code
Combatant::CharacterData Combatant::characters = {
/*Name */"SomeName",
/*Folder */"SomeFolder",
/*Offense */1.0f,
/*Defense */1.0f,
/*Combos */{
{KeyMemory(KeyMemory::MOVE_LEFT, KeyMemory::JUMP),
[&](int x) { this->moveLeft(); };
},
{KeyMemory(KeyMemory::MOVE_LEFT, KeyMemory::JUMP),
[&](int x) { this->moveLeft(); };
}
}
}
The CharacterData struct is defined by this code:
struct Combo {
KeyMemory controls;
void (*execute)(int);
};
struct CharacterData {
std::string name;
std::string folder;
float offense;
float defense;
Combo comboList[5];
};
Any help, would be much appreciated. ^_^
You might need to use a std::function<void(int)> to hold your lambda. (Particularly since you are using [&]).
Also, I'm not sure [&] actually makes sense in a global context. Maybe you should be passing in the object to call moveLeft on, and using []. Also, that change might let you use your simple function pointer instead of a std::function.
The problem turned out to be that Clang, which is the compiler used by Xcode/Apple doesn't yet support lambda functions. From what I read however the feature is coming in the future.

Problems with Static Initialization

I'm having some weird issues with static initalization. I'm using a code generator to generate structs and serialization code for a message passing system I wrote. In order to have a way of easily allocating a message based on it's message id I have my code generator ouput something similar to the following for each message type:
MessageAllocator s_InputPushUserControllerMessageAlloc(INPUT_PUSH_USER_CONTROLLER_MESSAGE_ID, (AllocateMessageFunc)Create_InputPushUserControllerMessage);
The MessageAllocator class basically looks like this:
MessageAllocator::MessageAllocator( uint32_t messageTypeID, AllocateMessageFunc func )
{
if (!s_map) s_map = new std::map<uint32_t, AllocateMessageFunc>();
if (s_map->insert(std::make_pair(messageTypeID, func)).second == false)
{
//duplicate key!
ASSERT(false, L"Nooooo!");
}
s_count++;
}
MessageAllocator::~MessageAllocator()
{
s_count--;
if (s_count == 0) delete s_map;
}
where s_map and s_count are static members of MessageAllocator. This works most of the time but sometimes messages are not added to the map. For example, this particular message is not added unless i call Create_InputPushUserControllerMessage() somewhere in my startup code, however other messages work fine. I thought this might be something to do with the linker incorrectly thinking the type is unreferenced and removing it so I disabled that using the /OPT:NOREF switch (I'm using Visual Studio 2008 SP1) but that had no effect.
I'm aware of the problem of the "static initialization order fiasco" but as far as I know the order in which these objects are created shouldn't alter the result so this seems ok to me.
Any insight here would be appreciated.
Put the static into a class so it is a static member of a class
struct InputPushUserControllerMessageAlloc { static MessageAllocator s_obj; };
MessageAllocator InputPushUserControllerMessageAlloc::s_obj(
INPUT_PUSH_USER_CONTROLLER_MESSAGE_ID,
(AllocateMessageFunc)Create_InputPushUserControllerMessage);
The Standard allows it to delay initialization of objects having namespace scope until any function/object from its translation unit is used. If the initialization has side-effect, it can't be optimized out. But that doesn't forbid delaying it.
Not so of objects having class-scope. So that might forbid it optimizing something there.
I would change s_map from a static class member into a static method member:
std::map<uint32_t,AllocateMessageFunc>& MessageAllocator::getMap()
{
// Initialized on first use and destroyed correctly on program termination.
static std::map<uint32_t,AllocateMessageFunc> s_map;
return s_map;
}
MessageAllocator::MessageAllocator( uint32_t messageTypeID, AllocateMessageFunc func )
{
if (getMap().insert(std::make_pair(messageTypeID, func)).second == false)
{
//duplicate key!
ASSERT(false, L"Nooooo!");
}
}
No need for destructor or a count.
If your global objects are in separate DLL's(or shared libs) that are lazy loaded.
This may cause a problem similar to your description.
You are not setting the pointer back to null.
MessageAllocator::~MessageAllocator()
{
s_count--;
if (s_count == 0)
{
delete s_map;
s_map = 0;
}
}
Turns out that the object files containing the static initializers were not included by the linker because nothing referenced any functions in them. To work around this I extern "C"-ed one of the generated functions so that it would have a predictable non-mangled name and then forced a reference to it using a pragma like this for each message
#pragma comment(linker, "/include:Create_GraphicsDynamicMeshCreationMessage")
which I put in the generated header file that is later included in all the other non-generated files. It's MSVC only and kind of hack but I assume I can do something similar on GCC once I eventually port it.