0

I know where error comes from. I have already marked it below the c++ code. I have no idea about this error. Hope someone help me. How to fix this problem?

The error is: Undefined symbols for architecture x86_64: "operator<<(std::__1::basic_ostream<char, std::__1::char_traits >&, Stack&)", referenced from: Path(int, int) in main.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)

#include <iostream>
using namespace::std;


template<class T>
class Stack{
public:
    Stack(int stackcapacity);
    bool Isempty()const;
    T& Top()const;
    void Push(const T& item);
    void Pop();
    friend ostream &operator<<(ostream &os, Stack<T> &s);
    
private:
    T* stack;
    int top;
    int capacity;

};

template<class T>
Stack<T>::Stack(int stackcapacity):capacity(stackcapacity){
    if(capacity<1)
        throw "stack capacity must be >0";
    stack=new T[capacity];
    top=-1;
}

template<class T>
inline bool Stack<T>::Isempty()const{
    return top==-1;
}

template<class T>
inline T& Stack<T>::Top()const{
    if(Isempty())
        throw"stack is empty";
    return stack[top];
}

template<class T>
void Stack<T>::Push(const T &x){
    if(top==capacity-1)
    {
        T *temp=new T[2*capacity];
        copy(stack,stack+capacity,temp);
        delete[]stack;
        stack=temp;
        capacity*=2;
    }
    stack[++top]=x;
}

template<class T>
void Stack<T>::Pop(){
    if(Isempty())
        throw "stack is empty";
    stack[top--].~T();
}

struct offsets{
    int a,b;
};
enum directions{N,NE,E,SE,S,SW,W,NW};

struct Items{
    int x,y,dir;
    Items(){};
    Items(int a,int b,int d){
        x=a;
        y=b;
        dir=d;
    }
};

template<class T>
ostream& operator<<(ostream& os,Stack<T>& s){

    os<<"top="<<s.top<<endl;
    for(int i=0; i<=s.top;i++){
        os<< i <<":"<<s.Stack[i]<<endl;
    }
    return os;
}
        
ostream& operator<<(ostream& os,Items& item){
    return os<< item.x<<","<<item.y<<","<<item.dir;
}



int maze[13][17] = {
        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        { 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1 },
        { 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1 },
        { 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1 },
        { 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1 },
        { 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1 },
        { 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 },
        { 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1 },
        { 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        { 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 },
        { 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1 },
        { 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1 },
        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
};

void Path(const int m,const int p){
    const offsets move[8]={{-1,0},{-1,1},{0,1},{1,1},{1,0},{1,-1},{0,-1},{-1,-1}};
    
    int mark[13][17]={0};
    mark[1][1]=1;
    Stack<Items> stack(m*p);
    Items temp(1,1,E);
    stack.Push(temp);
    
    while(!stack.Isempty()){
        temp=stack.Top();
        stack.Pop();
        int i=temp.x;
        int j=temp.y;
        int d=temp.dir;
        while(d<8){
            int g=i+move[d].a;
            int h=j+move[d].b;
            if((g==m)&&(h==p)){
                cout << stack;                //error comes from this row
                cout << i << " " << j << endl;
                cout << m << " " << p << endl;
                return;
            }
            if((!maze[g][h])&&(!mark[g][h])){
                mark[g][h]=1;
                temp.x=i;
                temp.y=j;
                temp.dir=d+1;
                stack.Push(temp);
                
                i=g;
                j=h;
                d=N;
            }
            else d++;
        }
    }
    cout << "No path in maze";
}

int main(int argc, const char * argv[]) {
    // insert code here...
    Path(11,15);
    return 0;
}

Henry
  • 13
  • 3
  • 1
    What is this mysterious object called `maze`, referenced in your `main()`? It's not declared anywhere. Is this real code that produces this compilation error, or modified/altered code? After replacing `maze` with `mark`, the shown code produces many other compilation errors. Please [edit] and fix your question so that the shown code produces ***only*** the compilation error you're asking about. – Sam Varshavchik Apr 11 '21 at 14:56
  • I get different errors here: [https://ideone.com/Nc7Iyq](https://ideone.com/Nc7Iyq) – drescherjm Apr 11 '21 at 14:58
  • @SamVarshavchik if I push all codes,it will be too long. – Henry Apr 11 '21 at 14:58
  • In that case you need to spend some time reducing the code to a smaller example that reproduces your exact error. – drescherjm Apr 11 '21 at 14:59
  • I have already put the complete code. – Henry Apr 11 '21 at 15:01
  • You should've put only [mcve] instead. Most of the posted code is completely unrelated to the problem. – user7860670 Apr 11 '21 at 15:05
  • Which part of a [mre] are you having trouble with? – Sam Varshavchik Apr 11 '21 at 15:06
  • sorry,I will try to reduce my problem. – Henry Apr 11 '21 at 15:09

2 Answers2

0

Friend declaration of operator << does not match existing operator << definition. It must be declared as template as well, otherwise it is treated as a separate non-template function which will be preferred during overload resolution but not implemented:

template<class xx_T>
friend ostream &operator<<(ostream &os, Stack<xx_T> &s);
user7860670
  • 35,849
  • 4
  • 58
  • 84
  • Thank you.I need time to understand it.if I have still have problem, hope you can help me. – Henry Apr 11 '21 at 15:23
0

This is a well-known problem with template friends. The problem it that a compiler treats a friend declaration as a non-template, but it is a template. If you insist on the out-of-class definition of operator<<, you can do the following:

template<class T>
class Stack;

template<class T>
std::ostream& operator<<(std::ostream&, const Stack<T>&);

template<class T>
class Stack {
public:
    friend std::ostream &operator<< <> (std::ostream&, const Stack<T>&);
};

template<class T>
std::ostream& operator<<(std::ostream&, const Stack<T>&) {
    //...
}

In other words, you should first tell a compiler that friend operator<< is a template.

Demo

Evg
  • 25,259
  • 5
  • 41
  • 83
  • Thank you.I need time to understand it.if I have still have problem, hope you can help me. – Henry Apr 11 '21 at 15:23