Related
I'm running a test with microsoft native unit testing framework (that comes with vs2019) and it fails with this message: Assert failed. Expected:<1> Actual:<1>
Here is the test code:
TEST_METHOD(memory_copy)
{
int ref[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int src[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int dest[10];
test::memory_copy<int>(src, dest, 10);
for (unsigned int i = 0; i < 10; i++)
{
Assert::AreSame(src[i], ref[i]);
Assert::AreSame(dest[i], ref[i]);
}
};
Note: memory_copy<>() copies memory from one pointer to another, just like std::memcpy()
Does anyone have an idea what may be the issue here?
Assert::AreSame() checks whether the inputs refer to the same object; it does not compare the values.
The implementation of the function (from CppUnitTestAssert.h) is as follows:
template<typename T> static void AreSame(const T& expected, const T& actual, const wchar_t* message = NULL, const __LineInfo* pLineInfo = NULL)
{
FailOnCondition(&expected == &actual, EQUALS_MESSAGE(expected, actual, message), pLineInfo);
}
What you can see here, is that it's comparing memory addresses, as opposed to the contents. Assert::AreEqual, on the other hand, compares the objects for equality.
template<typename T> static void AreEqual(const T& expected, const T& actual, const wchar_t* message = NULL, const __LineInfo* pLineInfo = NULL)
{
FailOnCondition(expected == actual, EQUALS_MESSAGE(expected, actual, message), pLineInfo);
}
It turns out that Assert::AreSame() doesn't do what I expected it to do. By changing it to Assert::AreEqual() I've solved the issue. More info here:
Microsoft Documentation on AreEqual()
Consider this code:
try {
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
} catch(std::out_of_range&) {
return false;
}
// <code>
std::cout<<a[b[42]]; // May throw std::out_of_range which should not be caught here.
return true;
<code> uses a and b. I have two options:
Put <code> in the try block
Take pointers in the try block, dereference them afterwards
The first option is wrong because if <code> throws std::out_of_range the function will return false, which should only happen if the map lookup fails.
The second option can be a bit ugly:
const Asdf *a;
const Bsdf *b;
try {
a = &map1.at(index1); // What?
b = &map2.at(index2);
} catch(std::out_of_range&) {
return false;
}
std::cout << (*a)[(*b)[42]];
return true;
Is there a better way? Something like try-except-else in Python would be nice, but that doesn't exist in C++.
It's not necessary to do any exception handling. std::map::find, given a key, will give you an iterator. If the element doesn't exist within the map, then find will return the end iterator (i.e. map.end()).
When de-referencing the iterator, you will receive a pair of values. The first being the key and the second being the object.
auto aIt = map1.find(index1);
auto bIt = map2.find(index2);
if(aIt == map1.end() || bIt == map2.end())
{
return false;
}
const Asdf &a = aIt->second;
const Bsdf &b = bIt->second;
std::cout << a[b[42]];
return true;
Note that iterators in C++ are defined such that the begin iterator is at the start and the end iterator is past the last element (http://en.cppreference.com/w/cpp/iterator/end), i.e. the range for iterators within a container is: [begin, end).
Solution 1:
Why include the code in the try catch, embedding it in its own try catch block to make the difference between the two cases?
try {
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
try {
// <code>
std::cout<<a[b[42]]; // May throw std::out_of_range which should not be caught here.
} catch (std::out_of_range&) {}
} catch(std::out_of_range&) {
return false;
}
return true;
But of course in this approach you can't forward to the outside of your function an out_of_range that would occur in your <code>.
Solution 2:
The other alternative is to simply check existence of the keys using map::count() without the need for exception catching:
if (map1.count(index1)==0 || map2.count(index2)==0) {
return false;
}
const Asdf &a = map1.at(index1);
const Bsdf &b = map2.at(index2);
// <code>
std::cout<<a[b[42]];
return true;
I like Miguel's solution the best, becuase it doesn't involve exception handling (when it is not called for).
But aside from that, here's another option (which I like for being short and keeping the low map operations count):
bool retval = false;
try{
const Asdf &a=map1.at(index1);
const Bsdf &b=map2.at(index2);
retval = true;
std::cout<<a[b[42]];
}catch(std::out_of_range&){
return reval;
}
// more code?
return reval;
An unconventional solution is to exploit the capturing of lambdas to extend the scope of the reference variables beyond the scope of the block. Since the objects referred by the references is valid beyond the scope block, the captured references aren't stale when used later as long as the map object remains in scope.
As an example
#include <functional>
#include <vector>
int main()
{
std::vector<std::vector< int > > map1 = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } };
std::function<int()> fn;
try{
const auto &a = map1.at(1);
const auto &b = map1.at(2);
fn = [&]() {return a[b[1]]; };
}
catch (std::out_of_range&){
return false;
}
fn(); // Any exception thrown here would be caught separately from the above try catch block
}
One work around is to ensure that map actually does contain the item. It adds to overhead, but is less worse of the many worse ways I know.
try{
map1.at(index1);
map2.at(index2);
}catch(std::out_of_range&){
return false;
}
const Asdf &a=map1.at(index1);
const Bsdf &b=map2.at(index2);
Or if written in a little better way (Sorry no performance gain, only readability) unless you want to sacrifice the constness of references.
if(map1.find(index1) == map1.end() || map2.find(index2) == map2.end()) return false;
const Asdf &a=map1.at(index1);
const Bsdf &b=map2.at(index2);
You can also use std::map::const_iterator without the need of try-catch block.
std::map::const_iterator a = map1.find(index1);
if(a == map1.end()) return false;
std::map::const_iterator b = map1.find(index2);
if(b == map2.end()) return false;
Do whatever with read-only a->second and b->second.
I am facing a problem while creating an array of derived class objects, and I can not find any explanation of this problem. The problem is the following:
I have an abstract base class RDMonitorBase and a derived class RDMonitorHashTable.
In another class RDMonitorPool I have the variable RDMonitorBase * m_rd_monitors.
In RDMonitorPool constructor I am creating an array of RDMonitorHashTable objects (using new)
and assigning them to m_rd_monitors.
Immediately after the construction, only the even number indexed RDMonitorHashTable objects are properly formed. The objects with odd numbered index have garbage in the member variables. I have no idea why this is happening.
The code and the GDB output on a breakpoint immediately after the construction are given below:
Relevant parts of the RDMonitorBase and RDMonitorHashTable classes are as follows. I have a virtual Access() method in Base which is not implemented in the derived, and a pure virtual RecordDistance() method. Access() calls the RecordDistance() method. This should be okay I think, a similar structure worked when I created simple examples.
class RDMonitorBase {
public:
RDMonitorBase();
virtual void StartMonitoring(const physical_address_t& target_address, const int core_id);
virtual Index Access(const physical_address_t& address, const int core_id);
bool IsActive() { return m_active; }
static const Index TRACKING_NOT_COMPLETE = -1;
protected:
virtual void RecordDistance(const physical_address_t& address) = 0;
const Index m_maximum_distance;
bool m_active;
physical_address_t m_target_address;
Index m_distance;
int m_core_id;
};
class RDMonitorHashTable: public RDMonitorBase {
public:
RDMonitorHashTable();
virtual void StartMonitoring(const physical_address_t& target_address,
const int core_id);
protected:
virtual void RecordDistance(const physical_address_t& address);
std::tr1::unordered_set<physical_address_t> m_address_set;
};
RDMonitorBase::RDMonitorBase():
m_maximum_distance(32),
m_active(false),
m_target_address(0),
m_distance(0),
m_core_id(-1) { ; }
Index RDMonitorBase::Access(const physical_address_t& address,
const int core_id) {
// ... some code
RecordDistance(address);
//... some other code
return m_distance;
}
RDMonitorHashTable::RDMonitorHashTable()
:RDMonitorBase() { ; }
void RDMonitorHashTable::RecordDistance(const physical_address_t& address) {
m_address_set.insert(address);
m_distance = m_address_set.size();
}
Now in the RDMonitorPool class constructor, the following is basically executed:
RDMonitorBase * m_rd_monitors = new (std::nothrow) RDMonitorHashTable[4096];
After this line executes, when I try to print the objects in gdb, I get this:
(gdb) print *(m_rd_monitors + 0)
$2 = {_vptr.RDMonitorBase = 0x7ffd93cacc90, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 32, m_active = false, m_target_address = 0, m_distance = 0, m_core_id = -1}
(gdb) print *(m_rd_monitors + 1)
$3 = {_vptr.RDMonitorBase = 0x1, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 68540736, m_active = 11, m_target_address = 0, m_distance = 4611686019492741120, m_core_id = 11}
(gdb) print *(m_rd_monitors + 2)
$4 = {_vptr.RDMonitorBase = 0x7ffd93cacc90, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 32, m_active = false, m_target_address = 0, m_distance = 0, m_core_id = -1}
(gdb) print *(m_rd_monitors + 3)
warning: can't find linker symbol for virtual table for `RDMonitorBase' value
$5 = warning: can't find linker symbol for virtual table for `RDMonitorBase' value
{_vptr.RDMonitorBase = 0x7ffda46b3e98, static TRACKING_NOT_COMPLETE = -1, m_maximum_distance = 68566480, m_active = 11, m_target_address = 0, m_distance = 4611686019492741120, m_core_id = 11}
So the even-indexed values have the proper values that are assigned in the constructor (for example 32 for m_maximum_distance). But the odd-index objexxts have garbage in m_maximum_distance and other members.
I will be extremely thankful if anybody can shed some light on why this is happening. Thanks!
Your problem is addressed here: Base pointer to array of derived objects
The problem is that the array is of type RDMonitorBase, so when you try to access any of its positions, the compiler calculates the offset according to RDMonitorBase instead of RDMonitorHashTable, effectively dereferencing the memory at the wrong point and thus slicing up the actual object which is of a different type. From the point your program access any position of that array, its bahavior becomes undefined.
The most straightforward alternative would be to use an array of pointers to the base type and assign an object of the derived class dynamicaly constructed to each of them.
RDMonitorBase* m_rd_monitors[4096];
for(std::size_t i = 0; i < 4096; ++i)
m_rd_monitors[i] = new (std::nothrow) RDMonitorHashTable;
I am attempting to determine at compile time if all the values in a std::initializer_list are unique. I was able to locate a solution to valiate the size of a list but have been unable to apply it to the contents. I have tried with both free functions and in constructors but both approaches have resulted in the following errors with GCC 4.7.2.
error: non-constant condition for static assertion
error: 'begin' is not a constant expression
I realize the members of std::initializer_list are not declared constexpr but I'm hoping there is a solution like the size validation. Is it possible to validate the contents at compile time using something like the following?
#include <initializer_list>
template<typename InputIterator>
constexpr bool Validate(InputIterator begin, InputIterator end)
{
static_assert(*begin == *end, "begin and end are the same");
// The actual implemetnation is a single line recursive check.
return true;
}
template<typename InputType>
constexpr bool Validate(const std::initializer_list<InputType>& input)
{
// "-1" removed to simplify and eliminate potential cause of error
return Validate(input.begin(), input.end() /* - 1 */);
}
int main()
{
Validate({1, 2, 1});
}
After some digging it looks like using std::initializer_list is not possible in GCC 4.7 due to the lack of constexpr in it's declaration. It should work with GCC 4.8 as <initializer_list> has been updated to include constexpr. Unfortunately using GCC 4.8 is not an option at the moment.
It is possible to access elements of an array if the decayed pointer is passed by reference though. This allows the validation to occur as desired but still isn't quite the solution I am hoping for. The following code is a workable solution for arrays. It still requires that the size of the array be supplied to the validation function but that it easy enough to correct.
#include <initializer_list>
template<typename T>
constexpr bool Compare(T& data, int size, int needleIndex, int haystackIndex)
{
return
needleIndex == haystackIndex ?
Compare(data, size, needleIndex + 1, haystackIndex)
: needleIndex == size ?
false
: data[needleIndex] == data[haystackIndex] ?
true
: Compare(data, size, needleIndex + 1, haystackIndex);
}
template<typename T>
constexpr bool Compare(T& data, int size, int index)
{
return
index == size ?
false
: Compare(data, size, index + 1) ?
true
: Compare(data, size, 0, index);
}
template<typename T, int ArraySize>
constexpr bool Validate(T(&input)[ArraySize], int size)
{
return !Compare(input, size, 0);
}
int main()
{
constexpr int initData0[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData1[] = {1, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData2[] = {2, 1, 2, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData3[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 8};
constexpr int initData4[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 7};
constexpr int initData5[] = {0, 1, 0, 3, 4, 5, 6, 7, 8, 9};
constexpr int initData6[] = {0, 1, 2, 3, 4, 5, 6, 9, 8, 9};
static_assert(Validate(initData0, 10), "set 0 failed"); // <-- PASS
static_assert(Validate(initData1, 10), "set 1 failed"); // <-- (and below) FAIL
static_assert(Validate(initData2, 10), "set 2 failed");
static_assert(Validate(initData3, 10), "set 3 failed");
static_assert(Validate(initData4, 10), "set 4 failed");
static_assert(Validate(initData5, 10), "set 5 failed");
static_assert(Validate(initData6, 10), "set 6 failed");
}
.
Build log:
C:\Source\SwitchCaseString\main.cpp: In function 'int main()':
C:\Source\SwitchCaseString\main.cpp:198:2: error: static assertion failed: set 1 failed
C:\Source\SwitchCaseString\main.cpp:199:2: error: static assertion failed: set 2 failed
C:\Source\SwitchCaseString\main.cpp:200:2: error: static assertion failed: set 3 failed
C:\Source\SwitchCaseString\main.cpp:201:2: error: static assertion failed: set 4 failed
C:\Source\SwitchCaseString\main.cpp:202:2: error: static assertion failed: set 5 failed
C:\Source\SwitchCaseString\main.cpp:203:2: error: static assertion failed: set 6 failed
Given these two functions :
bool logMessage(LogType_E, unsigned int, int, const char *, ...); //!< Log message with parameters
bool logMessage(LogType_E, int, const char *, ...); //!< Logs message with domain of Log class
And calling one of them :
A3D_LOG_INSTANCE.logMessage(Log::LOG_INFO, 0, "Number = %d", 10);
Error 1 error C2666: 'AX::Base::Log::logMessage' : 2 overloads have
similar
conversions o:\AX_FusRecAlg\src\base\test.u\LogSimpleFileTest\LogSimpleFileTest.cpp 50 AX.Base.LogSimpleFileTest
Could someone explain to me in plain English why this error occurs and possibly offer an alternative? I don't understand how the function which has 3 arguments before the char* matches with the function which has two arguments?!
Thanks.
Edit :
Since some of you are wondering that I am hiding information :
The function signature cannot be changed. No templates can be used. Just an explanation of why this error occurs would suffice.
enum LogType_E {
LOG_ERROR = 0, //!< error
LOG_WARNING = 1, //!< warning
LOG_SUCCESS = 2, //!< success
LOG_INFO = 3, //!< info
LOG_TRACE = 4, //!< trace message if tracing is enabled
LOG_TRACE1 = 5, //!< trace level 1
LOG_TRACE2 = 6, //!< trace level 2
LOG_TRACE3 = 7, //!< trace level 3
LOG_TRACE4 = 8 //!< trace level 4
};
bool logMessage(LogType_E, unsigned int, int, const char *, ...)
{
return true;
}
bool logMessage(LogType_E, int, const char *, ...)
{
return true;
}
int main()
{
logMessage(LOG_TRACE, 0, 0, "Teststring 2");
return 0;
}
Copy and paste above code into a .cpp file and run it or click here.
This is normal behaviour. From your example:
logMessage(LOG_TRACE, 0, 0, "Teststring 2");
Second parameter can be both, int and unsigned int.
You will have to make explicit cast to make it work.
For example:
logMessage(LOG_TRACE, (unsigned int)0, 0, "Teststring 2");