This is a very strange problem. I have two classes: a special console class (CConsole) and a test class (CHashTableTest), which I did to play with cards and unordered_maps to find out how they work.
In my console class, I have a public static CConsole member variable that provides a static console object for the rest of the project so that I can write to this console whenever I want. This works great for all my classes, including the testing class, but only when these test classes use a map, not an unordered_map!
The error I am getting is:
error LNK2001: unresolved external symbol "public static class CConsole CConsole: output" (? output @CConsole @@ 2V1 @A)
It comes from a class that calls methods on the test class, not the test class itself, but nothing strange happens in the calling class, it simply creates a CHashTableTest object (passed to the CConsole object) and calls Add and Get in the subject. It is placed in a separate project, but this is not a problem when I use the map, since the static member variable was made external using _declspec (ddlexport).
The solution is installed in Visual Studio 2012, the CConsole and CHashTableTest classes are located in the DLL project, which is the external link of the Unit Test project, where the call code exists.
CConsole and CHashTableTest Files:
Console.h
#ifndef _CONSOLE_H_
Console.cpp
#include "Console.h" CConsole CConsole::output = *new CConsole(OUTPUT_FILE, "C:/LocalProjects/---/output.txt");
HashTableTest.h
#ifndef _HASH_TABLE_TEST_H_ #define _HASH_TABLE_TEST_H_ #include <unordered_map> #include <map> #include <vector> #include "Debuggable.h" #include "Console.h" using namespace std; //template class __declspec(dllexport) unordered_map<int, double>; struct Hasher { public: size_t operator() (vector<int> const& key) const { return key[0]; } }; struct EqualFn { public: bool operator() (vector<int> const& t1, vector<int> const& t2) const { CConsole::output << "\t\tAdding, t1: " << t1[0] << ", t2: " << t2[0] << "\n"; // If I delete this line then no error! return (t1[0] == t2[0]); } }; class __declspec(dllexport) CHashTableTest : public CDebuggable { public: CHashTableTest(CConsole console = *new CConsole()); ~CHashTableTest(void); void Add(vector<int> key, bool value); bool Get(vector<int> key); private: CConsole m_console; unordered_map<vector<int>, bool, Hasher, EqualFn> m_table; // If I change this to a map then no error! }; #endif
Just to be clear, if I change the "unordered_map" above to "map" and remove the Hasher function object from the template argument list, this will compile. If I do not get a linker error. I did not include HashTableTest.cpp because it contains almost nothing.
EDIT
I'm not sure if I'm using unordered_map correctly, here is the implementation for the CHashTableTest class:
HashTableTest.cpp
#include "HashTableTest.h" CHashTableTest::CHashTableTest(CConsole console) : CDebuggable(console) { } CHashTableTest::~CHashTableTest(void) { } void CHashTableTest::Add(vector<int> key, bool value) { m_table[key] = value; } bool CHashTableTest::Get(vector<int> key) { return m_table[key]; }