3

I have this code:

template<typename T>
class Listoid{

  private:
    std::vector<T> list;

  public:
    typedef typename std::vector<T>::iterator iterator;

    iterator begin() {return list.begin();}
    iterator end() {return list.end();}

  public:
    Listoid(T t) {
      list.push_back(t);
    }

  const T operator [](int i){
    return list[i];
  }

  void addElem(T ne){
    list.push_back(ne);
  }

  friend T cons(T new_elem, Listoid<T> list);

};

template<typename T>
Listoid<T> cons(T new_elem, Listoid<T> list){

  Listoid<T> new_list(new_elem);
  for(typename Listoid<T>::iterator it = list.begin(), e = list.end();
        it != e; ++it){
          new_list.addElem(*it);
        }
  return new_list;
}


int main(){

  Listoid<int> lista(312);
  lista.addElem(22);

  Listoid<int> lista2 = cons(21, lista);

  return EXIT_SUCCESS;
}

But i cannot compile it; i get the following error:

/tmp/listoid-3kYCmd.o: In function `main':
listoid.cpp:(.text+0xda): undefined reference to `cons(int, Listoid<int>)'
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Maybe it's really simple, but i cannot solve it. Can someone help?

Aslan986
  • 9,984
  • 11
  • 44
  • 75
  • 1
    Your friend function's return type is wrong, it should be `Listoid`, not `T`. Though that's not the source of your problem. – Lily Ballard Sep 17 '12 at 20:09

4 Answers4

5

You must tell the compiler that cons is function template not simple function. Use this syntax:

friend T cons <>(T new_elem, Listoid<T> list);

Note <> after function name.

Otherwise it is searching for simple function, not function template. That is linker telling you.

[UPDATE]

And do not forget to add forward declaration of your function before its friend class, so your class will know what is the friend.

template<typename T>
Listoid<T> cons(T new_elem, Listoid<T> list);

[UPDATE2]

And change your type of your function template, and add forward declaration of your class. See:

template<typename T>
class Listoid;
template<typename T>
Listoid<T> cons(T new_elem, Listoid<T> list);

template<typename T>
class Listoid{
...

  friend Listoid<T> cons <>(T new_elem, Listoid<T> list);

};

That works for me: ideone

PiotrNycz
  • 23,099
  • 7
  • 66
  • 112
1

friend T cons(T new_elem, Listoid<T> list); is not a template, your later template<typename T> Listoid<T> cons(T new_elem, Listoid<T> list) is different overload of the cons() function. See FAQ.

wilx
  • 17,697
  • 6
  • 59
  • 114
1

Try to re-handle your function declaration with a template declaration and a correct return type :

   template<typename U> friend Listoid<U> cons(U new_elem, Listoid<U> list);

And rename your typename so it does not shadow the template type in your class template.

yves Baumes
  • 8,836
  • 7
  • 45
  • 74
  • That will make any `cons` function template specializations to be friend of any `Listoid` class template specialization. This is not what OP wants. OP wants that for the same `T` `Listoid` be friend to `cons`. – PiotrNycz Sep 17 '12 at 20:43
1

The problem is that you have two different declarations of cons, one in the friend declaration, another outside at namespace level. Friendship in templates is not as straightforward as it might look at the beginning, I recommend that you read this other answer with a long explanation of the different options. In particular, if you want (as it seems) to befriend only a particular specialization of the template you will need to provide the declaration upfront, before the class template:

template<typename T>
class Listoid;
template<typename T>
T cons(T new_elem, Listoid<T> list);
template<typename T>
class Listoid{
   friend T cons<T>(T,Listoid<T>);
...

In the current form you are declaring a non-template function to be a friend. That non-template function will be a better match than the template (non-templates are preferred over templates when the types match) and the compiler will generate a dependency towards the non-teplated function:

int const(int,Listoid<int>);
Community
  • 1
  • 1
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489