2

I started a template class that is supposed to manage a fixed length deque. I was looking to add a function that would return the data transformed into a vector. Because I cannot be sure this will be compiled with good NRVO (named return value optimization) and the data could in theory be quite large I decided to wrap the return in a unique_ptr (to avoid a massive call to copy constructors at the end). Oddly enough this did not compile:

 In file included from FixedDeque.cpp:8:
 FixedDeque.h:26: error: ISO C++ forbids declaration of 'unique_ptr' with no type
 FixedDeque.h:26: error: invalid use of '::'
 FixedDeque.h:26: error: expected ';' before '<' token
 FixedDeque.cpp:27: error: expected constructor, destructor, or type conversion before '<' token

I am on OS X snow leopard using g++ as the compiler in NetBeans.

However when I change exactly the same code to use auto_ptr the whole thing compiles. Is there an issue with unique_ptr and templates ? fyi, I did make sure there is a space between contiguous '<' and '>' in both cases (to avoid interpretation of pipe symbols).

Here is my code, I would really appreciate it if someone can shed light on the issue:

Header:

#include "deque"
#include "vector"
#include "memory"
template<typename T> class FixedDeque {
public:
  FixedDeque(int size);
  FixedDeque(const FixedDeque<T>& orig);
  virtual ~FixedDeque();
  // adding an auto_ptr/unique_ptr because not sure the C++ NRVO is applied in the compiler
  std::unique_ptr< std::vector<T> > getVectorCopy() const;
private:
  std::deque<T> _deq;
  int _maxSize;
};


#include "FixedDeque.h"
template<typename T> FixedDeque<T>::FixedDeque(int size)  : _deq(size), _maxSize(size)
{ }
template<typename T> FixedDeque<T>::FixedDeque(const FixedDeque<T>& orig) : _deq(orig._deq) {}
template<typename T> FixedDeque<T>::~FixedDeque() {}  
template<typename T> std::unique_ptr< std::vector<T> > FixedDeque<T>::getVectorCopy() const
{
    std::vector<T>* apVector = new std::vector<T>();
    return( std::unique_ptr< std::vector<T> >(apVector) );
}  

Again, simply replacing unique_ptr with auto_ptr does make the whole thing compile. I know my implementation returns a pointer to an empty vector. I just wanted to focus on what might be wrong with my usage of unique_ptr versus auto_ptr.

Thank you!

crogg01
  • 2,446
  • 15
  • 35
  • 1
    What is your C++ version? Have you enabled `-std=c++11` ? – masoud Oct 01 '13 at 16:53
  • It should be `#include ` etc. Are you using a C++11 compiler? – Kerrek SB Oct 01 '13 at 16:53
  • I am using NetBeans 7.3.1 which should have C++11 as standard. I set the C++ Standard to C++11 under "C++ Compiler" for the project properties and it gave me: cc1plus: error: unrecognized command line option "-std=c++11". So it looks like I might have to upgrade my g++ version. I got it from apple's XCode 3.x (the last snow leopard compatible version) - so probably need to just upgrade g++. – crogg01 Oct 01 '13 at 17:25

1 Answers1

0

Your code is mostly correct, except that you can't compile a class template. To make it work, you have to declare and implement the class template inside the header file, #include the header file and instantiate the class template on your program. See the example below:

// This is FixedDeque.hpp
#include <iostream>
#include <deque>
#include <vector>
#include <memory>

template<typename T> class FixedDeque {
public:
  FixedDeque(int size);
  FixedDeque(const FixedDeque<T>& orig);
  virtual ~FixedDeque();
  // adding an auto_ptr/unique_ptr because not sure the C++ NRVO is applied in the compiler
  std::unique_ptr< std::vector<T> > getVectorCopy() const;
private:
  std::deque<T> _deq;
  int _maxSize;
};

template<typename T> FixedDeque<T>::FixedDeque(int size)  : _deq(size), _maxSize(size)
{ }
template<typename T> FixedDeque<T>::FixedDeque(const FixedDeque<T>& orig) : _deq(orig._deq) {}
template<typename T> FixedDeque<T>::~FixedDeque() {}  
template<typename T> std::unique_ptr< std::vector<T> > FixedDeque<T>::getVectorCopy() const
{
    std::vector<T>* apVector = new std::vector<T>();
    return( std::unique_ptr< std::vector<T> >(apVector) );
}  

// This is FixedDeque_Test.cpp
int main() {
    FixedDeque<int> fdeque(10);
    std::unique_ptr<std::vector<int>> vec = fdeque.getVectorCopy();
    std::cout << vec->size() << std::endl;
    return 0;
}
Diego Giagio
  • 1,027
  • 7
  • 7
  • Hi Diego, Thanks so much for the quick reply. It definitely looks like a compiler problem. If you can my template to compile then you can definitely use it, the problem I had was that it refused to compile unless I used auto_ptr instead of unique_ptr. I copied and pasted your code and I am still getting the same issue (g++ on Snow Leopard). If what you meant was that I can put the template function implementations in the same file as the declarations, I did that too. Thanks for having a go. – crogg01 Oct 01 '13 at 17:13
  • 1
    @user2835640 like others said you need to enable the c++11 support with your compiler to use std::unique_ptr. – drescherjm Oct 01 '13 at 17:19
  • @user2835640 Okay, on Snow Leopard you probably don't have a C++11 compiler. Can you try g++ -std=c++11 FixedDeque.cpp -o FixedDeque? You can also try with clang, like this: clang++ -std=c++11 -stdlib=libc++ FixedDeque.cpp -o FixedDeque. Please put the entire code from my answer on a single file before compiling. – Diego Giagio Oct 01 '13 at 17:20
  • Diego, drescherjm, thanks for the spot. as I mentioned in a comment above I probably need to find a way to upgrade just my g++ on Snow Leopard without destroying anything else. I will debate that decision but for now I will consider the issue resolved. It is an interesting error to see (using the unique_ptr template in a non C++11 environment). Thanks people - looks like a really useful site for help. I will also try installing clang compiler. – crogg01 Oct 01 '13 at 17:29
  • @user2835640 Try updating your XCode to the latest version. It will bring a newer clang with C++11 support and you will be able to compile this without problems. – Diego Giagio Oct 01 '13 at 17:31
  • I actually had the latest XCode before but the Xcode IDE refused to execute on a Snow Leopard system, maybe it would work if I just used the compilers. Thanks for the suggestion (don't really use the IDE anyway). – crogg01 Oct 01 '13 at 17:33