0

I don't understand why it's not compiling correctly, the linker reports missing symbols:

Undefined symbols for architecture x86_64: "bool swinadventure::Utils::is_last<__gnu_cxx::__normal_iterator > >, std::vector > >(__gnu_cxx::__normal_iterator > >, std::vector > const&)", referenced from: swinadventure::Inventory::get_item_list(std::string, std::string) in Inventory.cpp.o

Because eariler in the process I also see this error: /usr/bin/ranlib: file: liblibswinadventure.a(Utils.cpp.o) has no symbols I assume that it's not compiling the utils file correctly for some reason.

For reference, I'm using CMake on a Mac OS X 10.7 system with most homebrew tools installed and linked.

Utils.h

#ifndef UTILS_H_
#define UTILS_H_

#include <vector>

namespace swinadventure {

/**
 * Static class for various utilities and helper functions
 */
class Utils {
public:
    template <typename Iter>
    static Iter next_iterator(Iter iter);
    template <typename Iter, typename Cont>
    static bool is_last(Iter iter, const Cont& cont);
};

} /* namespace swinadventure */
#endif /* UTILS_H_ */

Utils.cpp

#include "Utils.h"

namespace swinadventure {

/**
 * Returns the next iterator
 * http://stackoverflow.com/questions/3516196/testing-whether-an-iterator-points-to-the-last-item
 * @param iter
 * @return
 */
template <typename Iter>
Iter Utils::next_iterator(Iter iter) {
    return ++iter;
}

/**
 * Checks if the iterator is the last of the vector array
 * http://stackoverflow.com/questions/3516196/testing-whether-an-iterator-points-to-the-last-item
 * @param iter  iterator
 * @param cont  vector array
 * @return
 */
template <typename Iter, typename Cont>
bool Utils::is_last(Iter iter, const Cont& cont)
{
    return (iter != cont.end()) && (next_iterator(iter) == cont.end());
}

} /* namespace swinadventure */
Adam M-W
  • 3,509
  • 9
  • 49
  • 69
  • 1
    Duplicate of so many questions with this problem. – Puppy Sep 15 '12 at 16:06
  • such as http://stackoverflow.com/questions/1639797/template-issue-causes-linker-error-c?rq=1 – WhozCraig Sep 15 '12 at 16:37
  • possible duplicate of [Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – Aaron McDaid Sep 15 '12 at 18:24

2 Answers2

1

Move your template function definitions to the header.

The linker is telling you that while compiling Inventory.cpp, a special instantiation of Utils::is_last was needed, but the definition wasn't available to create it.

And while compiling Utils.cpp, the definition of Utils::is_last was available, but that instantiation wasn't needed.

So neither source file was able to create that function while compiling.

Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
1

When you declare a template, the variables inside the <> become stand-ins for the type passed, and as such these variables are used in the same way as classes and only need to be declared once. Thus template <typename Iter, typename Cont> can should be treated as if it were a class definition, and moved outside of the class Utils { definition. The other instances of template should be removed as well, especially before the Utils::func() definitions. As it stands now, you're basically telling it "Create a class named Iter. Create a class named Iter. Create a class named Iter, etc." As soon as it encounters a variable of the type 'Iter', it doesn't know which one it should use. This site should help with templates, and is worth the look:

http://www.parashift.com/c++-faq/templates.html

Ghost2
  • 536
  • 3
  • 13