How can I compare two C++11 std::functions with operator==, and return true if both of said functions refer to the same f
Well, if you are not afraid of hacks, you can do something like this:
// Simple function means no std::bind was used
bool IsSimpleFunction(std::function function)
{
typedef void(functionType)(Args...);
functionType** functionPointer = function.template target();
return functionPointer != NULL;
}
bool AreEqual(std::function left, std::function right)
{
const int size = sizeof(std::function);
std::byte leftArray[size] = { {(std::byte)0} };
std::byte rightArray[size] = { {(std::byte)0} };
std::byte* leftByte = (std::byte*) new (&leftArray) std::function(left);
std::byte* rightByte = (std::byte*) new (&rightArray) std::function(right);
// PrintFunctionsBytes(leftByte, rightByte, size);
// Here the HACK starts
// By resetting certain values we are able to compare functions correctly
// When values are reset it has the same effect as when these values are ignored
bool isSimpleFunction = IsSimpleFunction(left);
if (!isSimpleFunction)
{
ResetAt(leftArray, rightArray, 16);
}
ResetAt(leftArray, rightArray, 56);
ResetAt(leftArray, rightArray, 57);
// Here the HACK ends
for (int i = 0; i < size; i++, leftByte++, rightByte++)
{
if (*leftByte != *rightByte)
{
return false;
}
}
return true;
}
void ResetAt(std::byte* leftArray, std::byte* rightArray, int i)
{
leftArray[i] = (std::byte)0;
rightArray[i] = (std::byte)0;
}
// Only for debug
void PrintFunctionsBytes(std::byte* leftFirstByte, std::byte* rightFirstByte, unsigned long long size)
{
std::vector leftVector(leftFirstByte, leftFirstByte + size);
std::vector rightVector(rightFirstByte, rightFirstByte + size);
std::cout << "Left: ";
for (int i = 0; i < size; i++)
{
std::cout << i << ':' << (int)leftVector[i] << std::endl;
}
std::cout << "Right: ";
for (int i = 0; i < size; i++)
{
std::cout << i << ':' << (int)rightVector[i] << std::endl;
}
}
This was tested in MSVC and on 64 bit release configuration. And it was working for simple functions and for std::bind converted to std::function.
If you have different compiler or build configuration, you'll have to adjust ignored bytes for your environment.
Complete example here: https://github.com/linksplatform/Delegates