mercredi 22 mai 2019

How to separate the interface from the implementation when using alias templates whith std::shared_ptr?

I have the following in a header file

template<typename T>class StackNode; // foward declaration
template<typename T>using Node = std::shared_ptr<StackNode<T>>; // alias template

If I put the definition in the same file everything works fine, the problem come when i try to separate the interface from the implementation in a separate cpp file.

file: main.cpp

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

int main() {
    Node<char> node(new StackNode<char>('A'));

    return 0;
}

file: stacknode.h

#ifndef STACKNODE_H
#define STACKNODE_H

#include <iostream>
#include <memory>

template<typename T>class StackNode; // foward declaration
template<typename T>using Node = std::shared_ptr<StackNode<T>>; // alias template

template<typename T>
class StackNode {
private:
    T data;
    Node<T> next_node;

public:
    explicit StackNode(T data = 0, Node<T> next_node = nullptr);
    ~StackNode();

    T getData() const;
    Node<T> getNextNode() const;
};

#endif // STACKNODE_H


// this givesme error when try to punt in a separated file (stacknode.cpp)
template<typename T>
StackNode<T>::StackNode(T data, Node<T> next_node)
    : data(data), next_node(next_node)
{
    std::cout << "Constructor::Node(" << data << ")" << "\n";
}

template<typename T>
StackNode<T>::~StackNode()
{
    std::cout << "Destructor::Node(" << data << ")" << "\n";
}

template<typename T>
T StackNode<T>::getData() const {
    return data;
}

template<typename T>
Node<T> StackNode<T>::getNextNode() const {
    return next_node;
}


Console output

Constructor::Node(A)
Destructor::Node(A)

if i try to compile while having definitions in a separate file got this:

/usr/bin/ld: /tmp/ccjJDKDZ.o: in function `main':
main.cpp:(.text+0x48): undefined reference to `StackNode<char>::StackNode(char, std::shared_ptr<StackNode<char> >)'
/usr/bin/ld: /tmp/ccjJDKDZ.o: in function `std::__shared_count<(__gnu_cxx::_Lock_policy)2>::__shared_count<StackNode<char>*>(StackNode<char>*)':
main.cpp:(.text._ZNSt14__shared_countILN9__gnu_cxx12_Lock_policyE2EEC2IP9StackNodeIcEEET_[_ZNSt14__shared_countILN9__gnu_cxx12_Lock_policyE2EEC5IP9StackNodeIcEEET_]+0x56): undefined reference to `StackNode<char>::~StackNode()'
/usr/bin/ld: /tmp/ccjJDKDZ.o: in function `std::_Sp_counted_ptr<StackNode<char>*, (__gnu_cxx::_Lock_policy)2>::_M_dispose()':
main.cpp:(.text._ZNSt15_Sp_counted_ptrIP9StackNodeIcELN9__gnu_cxx12_Lock_policyE2EE10_M_disposeEv[_ZNSt15_Sp_counted_ptrIP9StackNodeIcELN9__gnu_cxx12_Lock_policyE2EE10_M_disposeEv]+0x1e): undefined reference to `StackNode<char>::~StackNode()'
collect2: error: ld returned 1 exit status

Why? and How to solve? Thanks in advance

Aucun commentaire:

Enregistrer un commentaire