0

I'm trying to use my table1.h file and and my table1.template file but everytime I declare a table variable with a data type I get this error

1>DataStructuresLab21V2.obj : error LNK2019: unresolved external symbol "public: __thiscall table<char>::table<char>(void)" (??0?$table@D@@QAE@XZ) referenced in function _wmain

I have checked the spelling, I have table() declared in my header file and implemented in my table1.template file, the casing is correct between the header and the template file. I don't know where this error lies in my code and any help identifying any places where there is an error would be appreciated. The programming language is c++ and was done in Visual Studio 2013. The header and template file was provided by my professor for the assignment which was to modify the files to implement double hashing. Thanks in advance

This is my header file called table1.h

// FILE: table1.h (part of the namespace main_savitch_12A)
// TEMPLATE CLASS PROVIDED: table<RecordType> (a table of records with            keys).
//    This class is a container template class for a table of records.
//    The template parameter, RecordType, is the data type of the records in the
//    table. It may be any of the bulit-in C++ types (int, char, etc.), or a
//    class with a default constructor, an assignment operator, and an integer
//    member variable called key.
// 
// MEMBER CONSTANT for the table<RecordType> class:
//   static const size_type CAPACITY = ________
//     table<RecordType>::CAPACITY is the maximum number of records held by a table.
//
// CONSTRUCTOR for the table<RecordType> template class:
//   table( )
//     Postcondition: The table has been initialized as an empty table.
//
// MODIFICATION MEMBER FUNCTIONS for the table<RecordType> class:
//   void insert(const RecordType& entry)
//     Precondition: entry.key >= 0. Also if entry.key is not already a key in
//     the table, then the table has space for another record
//     (i.e., size( ) < CAPACITY).
//     Postcondition: If the table already had a record with a key equal to
//     entry.key, then that record is replaced by entry. Otherwise, entry has
//     been added as a new record of the table.
//
//   void remove(int key)
//     Postcondition: If a record was in the table with the specified key, then
//     that record has been removed; otherwise the table is unchanged.
//
// CONSTANT MEMBER FUNCTIONS for the table<RecordType> class:
//   bool is_present(const Item& target) const
//     Postcondition: The return value is true if there is a record in the
//     table with the specified key. Otherwise, the return value is false.
//
//   void find(int key, bool& found, RecordType& result) const
//     Postcondition: If a record is in the table with the specified key, then
//     found is true and result is set to a copy of the record with that key.
//     Otherwise found is false and the result contains garbage.
//
//    size_type size( ) const
//      Postcondition: Return value is the total number of records in the
//      table.
//
//  VALUE SEMANTICS for the table<RecordType> template class:
//    Assignments and the copy constructor may be used with table objects.

#ifndef TABLE1_H
#define TABLE1_H
#include <cstdlib>    // Provides size_t
using namespace std;

    template <class RecordType>
    class table
    {
    public:
        // MEMBER CONSTANT -- See Appendix E if this fails to compile.
        static const size_t CAPACITY = 811;
        // CONSTRUCTOR
        table();
        // MODIFICATION MEMBER FUNCTIONS
        void insert(const RecordType& entry);
        void remove(int key);
        // CONSTANT MEMBER FUNCTIONS
        bool is_present(int key) const;
        void find(int key, bool& found, RecordType& result) const;
        size_t size() const { return used; }
    private:
        // MEMBER CONSTANTS -- These are used in the key field of special      records.
        static const int NEVER_USED = -1;
        static const int PREVIOUSLY_USED = -2;
        // MEMBER VARIABLES
        RecordType data[CAPACITY];
        size_t used;
        // HELPER FUNCTIONS
        size_t hash(int key) const;
        size_t hash2(int key) const;
        size_t next_index(size_t index) const;
        void find_index(int key, bool& found, size_t& index) const;
        bool never_used(size_t index) const;
        bool is_vacant(size_t index) const;
    };


#endif

This is my template file

#include "stdafx.h"
#include <cassert>
#include <cstdlib>
#include "table1.h"


using namespace std;

template<class RecordType>
size_t table<RecordType>::CAPACITY;

template <class RecordType>
const int table<RecordType>::NEVER_USED;

template <class RecordType>
const int table<RecordType>::PREVIOUSLY_USED;

template<class RecordType>
table<RecordType>::table()
{
    size_t i;
    used = 0;
    for (i = 0; i < CAPACITY; i++)
        data[i].key = NEVER_USED;
}

template<class RecordType>
void table<RecordType>::insert(const RecordType& entry)
{
    bool already_present;
    size_t index;

    assert(entry.key >= 0)

    find_index(entry.key, already_present, index);

    if (!already_present)
    {
        assert(size() < CAPACITY)
            index = hash(entry.key);
        while (!is_vacant(index))
            index = next_index(index);
        ++used;
        data[index] = entry;
    }
    else if (already_present)
    {
        assert(size() < CAPACITY)
            index = hash(entry.key) - hash2(entry.key);
        while (!is_vacant(index))
            index = next_index(index);
        ++used;
        data[index] = entry;
    }


}

template <class RecordType>
void table<RecordType>::remove(int key)
// Library facilities used: cassert
{
    bool found;        // True if key occurs somewhere in the table
    std::size_t index;   // Spot where data[index].key == key

    assert(key >= 0);

    find_index(key, found, index);
    if (found)
    {   // The key was found, so remove this record and reduce used by 1.
        data[index].key = PREVIOUSLY_USED; // Indicates a spot that's no longer in use.
        --used;
    }
}

template <class RecordType>
bool table<RecordType>::is_present(int key) const
// Library facilities used: assert.h
{
    bool found;
    std::size_t index;

    assert(key >= 0);

    find_index(key, found, index);
    return found;
}

template <class RecordType>
void table<RecordType>::find(int key, bool& found, RecordType& result) const
// Library facilities used: cassert.h
{
    size_t index;

    assert(key >= 0);

    find_index(key, found, index);
    if (found)
        result = data[index];
}

template <class RecordType>
inline size_t table<RecordType>::hash(int key) const
{
    return (key % CAPACITY);
}

template<class RecordType>
inline size_t table<RecordType>::hash2(int key) const
{
    return(key % hash(key));
}


template <class RecordType>
inline size_t table<RecordType>::next_index(size_t index) const
// Library facilities used: cstdlib
{
    return ((index + 1) % CAPACITY);
}

template <class RecordType>
void table<RecordType>::find_index(int key, bool& found, size_t& i) const
// Library facilities used: cstdlib
{
    size_t count; // Number of entries that have been examined

    count = 0;
    i = hash(key);
    while ((count < CAPACITY) && (data[i].key != NEVER_USED) && (data[i].key != key))
    {
        ++count;
        i = next_index(i);
    }
    found = (data[i].key == key);
}

template <class RecordType>
inline bool table<RecordType>::never_used(size_t index) const
{
    return (data[index].key == NEVER_USED);
}

template <class RecordType>
inline bool table<RecordType>::is_vacant(size_t index) const
{
    return (data[index].key == NEVER_USED) || (data[index].key == PREVIOUSLY_USED);
}
Karl Nicoll
  • 16,090
  • 3
  • 51
  • 65
user3354383
  • 47
  • 1
  • 1
  • 9
  • You have to include both files in the source file where you declare your variable. – Alan Stokes Apr 24 '16 at 22:44
  • Possible duplicate of [What is an undefined reference/unresolved external symbol error and how do I fix it?](http://stackoverflow.com/questions/12573816/what-is-an-undefined-reference-unresolved-external-symbol-error-and-how-do-i-fix) – Ken White Apr 24 '16 at 22:57

1 Answers1

0

You're not #includeing your table1.template file inside your header file.

The last line before the #endif in your header file has to be #include "table1.template"

For example:

        bool is_vacant(size_t index) const;
    };

#include "table1.template"

#endif

Additionally you must remove the #include "table1.h" line from your template file:

#include "stdafx.h"
#include <cassert>
#include <cstdlib>
#include "table1.h"   //<-- Remove this line.

Alternatively, you can #include both files wherever you are using them:

#include "table1.h"
#include "table1.template"
#include "SomeType.h"
// Other #include statements here.

int main()
{
    table<SomeType> myTable;

    // ...stuff...

   return 0
}

Template classes must have all definitions available whenever the template is used because the contents of the .template file are not compiled in the standard .h/.cpp way. This is because a separate class instance is defined for each different <class RecordType> that you use, and so the compiler needs both the .h file and .template file to be #included before table<MyType> is used.

Karl Nicoll
  • 16,090
  • 3
  • 51
  • 65
  • I have tried that solution but then when I go to build it, the compiler gives me a whole set of errors. This is has happened before and I had the Teaching Assistant and Professor look at it but they didn't know how to fix it. This is only a few the compiler gives 1>c:\users\ishraq\documents\visual studio 2013\projects\datastructureslab21v2\datastructureslab21v2\table1.template(10): error C2143: syntax error : missing ';' before '<' – user3354383 Apr 24 '16 at 22:57
  • @user3354383 - Have you removed `#include "table1.h"` from the table1.template file? I have edited my answer, see above. – Karl Nicoll Apr 24 '16 at 22:59
  • If my assumption is correct, then you mean put both the include statements for the header and template file in main where I'm trying to use table in which i did see below: – user3354383 Apr 24 '16 at 23:04
  • #include "stdafx.h" #include "table1.h" #include "table1.template" using namespace std; int _tmain(int argc, _TCHAR* argv[]) { table table3; return 0; } – user3354383 Apr 24 '16 at 23:04
  • yea that's exactly what I did but I'm still getting the same errors – user3354383 Apr 24 '16 at 23:07
  • @user3354383 - To be clear, you need to `#include` them whereever you are creating variables of type `table`. So if, for example, you create a `table` variable inside your main() function, you need to `#include` the table1.h and table1.template files inside your `DataStructuresLab21V2.cpp` file. – Karl Nicoll Apr 24 '16 at 23:09
  • I have them both declared in the DataStructuresLab21V2.cpp file with the #include statements since that is the only file I'm using the table variable but I'm still getting the same errors. Keep in mind I'm using the DataStructuresLab21V2.cpp file to use the methods from the other files, I just wanted to clear that up so there is no confusion – user3354383 Apr 24 '16 at 23:17
  • Are these still the same errors you mention in the question? Or are the errors different from your question? I'd be inclined to think that you have a [circular reference](https://stackoverflow.com/questions/625799/resolve-circular-dependencies-in-c) with your `#include` statements. – Karl Nicoll Apr 24 '16 at 23:21
  • No, these errors are different. Here are some that the compiler is giving me: error C2143: syntax error : missing ';' before '<' , error C2988: unrecognizable template declaration/definition, syntax error : '<'. – user3354383 Apr 24 '16 at 23:35
  • @user3354383 - At a guess, these are syntax errors in your .template file. If you've never `#include`'d your .template file before, it has likely never been checked for errors by the compiler. A couple of things I can think of from looking at your template file. I would work through your compiler errors as you would do normally, and ask another question on here if you need additional help :-) – Karl Nicoll Apr 24 '16 at 23:43
  • No worries. C++ templates are a complex beast :). Don't hesitate to ask another question if you get stuck! – Karl Nicoll Apr 24 '16 at 23:50