0

There are quite a few posts like this on Stack Overflow, but most of them pertain to Xcode, and I cannot replicate their solutions. I have a Heap.h, Heap.cpp, and main.cpp file and whenever I try to run main.cpp with g++ main.cpp Heap.cpp, it gives me:

clang: error: linker command failed with exit code 1 (use -v to see invocation)

File Heap.h

#ifndef _HEAP_H_
#define _HEAP_H_

template<class T>
class Heap{
    private:
        struct Node{
            T *dist;
            T *v;

            bool operator==(const Node& a){
                return *dist == *(a -> dist);
            }

            bool operator!=(const Node& a){
                return (!(*dist == *(a -> dist)));
            }

        };

        Node *container;
        int size;
        int curSize;
        T sourceV;

    public:
        Heap();
        Heap(int inSize, T inSourceV);

};

#endif

File Heap.cpp

#include <iostream>
#include <vector>
#include <limits>
#include "Heap.h"

using namespace std;

template<class T>
Heap<T>::Heap(){
    cout << "hello" <<endl;
}

template<class T>
Heap<T>::Heap(int inSize, T inSourceV){
    size = inSize;
    container = new Node[size];
    curSize = 0;
    sourceV = inSourceV;

    int maxVal = numeric_limits<int>::max();
    for (int i = 1; i < size; i++){
        container[i].dist = &maxVal;
        container[i].v = &maxVal;
    }
}

File main.cpp

#include "Heap.h"
#include <iostream>

using namespace std;

int main(){
   Heap <int> h;
}

It is strange I have another project that contains bst.h, bst.cpp, and main.cpp, and those run fine. The difference between these two projects is that the bst I implemented is not a templated class.

I also saw another similar post that mentioned something about changing bitcode settings, but where can I access that from?

I'm running Xcode 7.1. Apple LLVM version 7.0.0 (clang-700.1.76).
Target: x86_64-apple-darwin14.5.0
Thread model: posix

1
  • 3
    Did you try what the message suggests? Call with -v and see what was actually happening there? Commented Nov 16, 2015 at 16:08

1 Answer 1

2

You don't instantiate a Heap<int> in the Heap.cpp compilation. As a result the compiler doesn't bother generating any code for Heap.o.

You can see this if you do:

nm Heap.o

It tells you there's nothing there.

This is a typical behaviour of a C++ compiler - no template gets turned into code unless there's an instantiation of it.

Quick solutions are

  1. Move all the Heap.cpp code into the template class declaration of Heap.h
  2. create a dummy function in Heap.cpp that instantiates a Heap<int>
Sign up to request clarification or add additional context in comments.

8 Comments

Never would have caught this. Just curious, is that why there are some templated classes that end in .inl instead of .cpp? To get around this instantiation problem? Because if we would have to instantiate Heap to a specific type, wouldn't this defeat the purpose of templates?
The use of .inl is only a hint for developers. It implies that the code should be inlined e.g. by #include in a .cpp file, but that's only an expectation. Templates are just that - a template. They don't resolve into actual code until the template is instantiated. As a result; a template on it's own can't be split between a .h and .cpp file; as without instantiation; there won't be any code created that can be linked to.
the quick solutions you mentioned, is one better than the other?
The most correct solution is moving the template code into the .h. The second will only solve the problem of Heap<int> in that case, and if you create a Heap<float> then it wouldn't work. I only classed it as quick because there's very little code in there to move.
Another hack is just explicit instantiation by including "template Heap<int>;" in the definitions file. Suffers the same problem as a dummy function as it only instantiates the <int> template. It all should be in the header.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.