I'm getting this error from the linker:
1>PACBalancesTest.obj : error LNK2001: unresolved external symbol "public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const " (??RBalChgKeyComparator@PAC@@QBE_NABVBalChgKey@1@0@Z)
I must be missing something really obvious, because I've looked at the definition of the "missing" symbol repeatedly and can't see any problem.
The symbol's definition is in a .lib file. I see the following in the output from dumpbin /symbols on that .lib file:
2F0 00000000 SECTFD notype () External | ??RBalChgKeyComparator@PAC@@QBE_NABVBalChgKey@1@0@Z (public: bool __thiscall PAC::BalChgKeyComparator::operator()(class PAC::BalChgKey const &,class PAC::BalChgKey const &)const )
And there are other symbols being resolved successfully from that .lib file! (In fact, from the same .obj.) [Update: I no longer think the preceding statement is true. This may be my first attempt to access any function not defined in a .h file.]
WHAT FOLLOWS IS NOT RELEVANT TO THE PROBLEM -- SO PLEASE DON'T SPEND TIME STUDYING IT!
Here's the declaration of the function (in PACBalances.h):
namespace PAC {
class BalChgKey {
public:
...
};
struct BalChgKeyComparator {
bool operator()(const BalChgKey& lhs, const BalChgKey& rhs) const;
};
typedef std::multimap<BalChgKey, long, BalChgKeyComparator> BalChgKeyLongMMap;
};
Note that I've tried changing 'struct' above to 'class', with no effect.
Here is the calling code (in a cpputest test file):
#include "CppUTest/TestHarness.h"
#include <utility>
#include <map>
#include "PACBalances.h"
using namespace PAC;
...
TEST_GROUP(PACBalanceCUMap)
{
BalChgKeyLongMMap empty;
BalChgKeyLongMMap onesy;
void setup()
{
// **Adding the following line caused this error to start to occur.**
onesy.insert(std::pair<BalChgKey, long>(BalChgKey(BOPCAT_FEE, PAYMTYPE_OVERDRAFT_FEE, 4321, 41100, 1, 17), 17));
}
void breakdown()
{
}
};
And here is the definition of the operator function itself:
bool PAC::BalChgKeyComparator::operator()(
const BalChgKey& thing1,
const BalChgKey& thing2
) const
{
if (thing1.m_balKey.m_balCat < thing2.m_balKey.m_balCat) return true;
else if (thing1.m_balKey.m_balCat > thing2.m_balKey.m_balCat) return false;
// Fall thru if balCats are equal
...
return false;
}
Please note that:
- The comparator, and the typedef'd multimap, works beautifully in lots of code (not shown above).
- The test file calls lots of other functions declared and defined in that .h file, but this is the first time I've tried calling a function defined in a separate .cpp file.
- My question is not why does the 'onesy.insert' call requires the comparator function. I understand that. It just happens to be the first multimap operation that I've coded in the test set that actually uses the comparator.
I have various hunches, but I'm running out of them, so if someone who knows about this stuff can give me any leads I would be very grateful.
Norm
@panta rei: You provided the key in your comment. (Sorry, can't figure out how to type Greek letters here.)
The problem was basically that I didn't know how to tell Visual Studio what objects to link in. I had told my solution that AnalyticsUTest depended on AnalysticsUTested, but the linking step is performed by the project (AnalyticsUTest), not the solution, so I needed to tell the project to include this .lib file.
So I went to the project's properties sheet and created two new macros, one giving the folder where VS was putting my .lib file (ANALYTICSUTESTED_LIB_PATHS), the other giving the name of my .lib file (ANALYTICSUTESTED_LIB_DEPENDENCIES) -- both by analogy with the CPPUTEST_LIB* macros.
And then I added $(ANALYTICSUTESTED_LIB_PATHS) to Linker > General > Additional Library Directories. And I added $(ANALYTICSUTESTED_LIB_DEPENDENCIES) to Linker > Input > Additional Dependencies.
And that fixed my problem! (I've spelled it out here in case another newbie like me comes along and needs it.)
Thank you, panta rei. How do I give you points for an answer provided via a comment?