0

I keep getting expected primary expression when trying to pass a template parameter to a function call..

My Error looks like:

In PtrAllocator<T, Pool>::allocate(PtrAllocator<T, Pool>::size_type, const void*)': expected primary-expression before '>' token

In PtrAllocator<T, Pool>::max_size() const': expected primary-expression before '>' token

My code looks like:

template<typename T, typename Pool>
class PtrAllocator : public BasicAllocator<T>
{
    private:
        Pool pool;

    public:
        typedef typename BasicAllocator<T>::pointer pointer;
        typedef typename BasicAllocator<T>::size_type size_type;
        typedef typename BasicAllocator<T>::value_type value_type;

        template<typename U>
        struct rebind {typedef PtrAllocator<U, Pool> other;};

        PtrAllocator(Pool&& pool) : pool(pool) {}

        pointer allocate(size_type n, const void* hint = 0) {return static_cast<pointer>(pool.allocate<T>(n, hint));}
        void deallocate(void* ptr, size_type n) {pool.deallocate(static_cast<pointer>(ptr), n);}
        size_type max_size() const {return pool.max_size<T>();}
};

class Pool
{
    public:
        template<typename T>
        void* allocate(std::size_t n, const void* hint = 0) {return ::operator new(n * sizeof(T));}

        template<typename T>
        void deallocate(T* ptr, std::size_t n) {::operator delete(ptr);}

        template<typename T>
        std::size_t max_size() const {return std::numeric_limits<std::size_t>::max() / sizeof(T);}
};

int main()
{
    PtrAllocator<int, Pool> alloc = PtrAllocator<int, Pool>(Pool());
    std::vector<int, PtrAllocator<int, Pool>> v(alloc);
    v.resize(1000); //this line is causing the error.
}

The errors happen when PtrAllocator::allocate calls Pool::allocate. The same thing happens to max_size but does not happen to deallocate. Any ideas why it won't let me specify the template parameter?

Brandon
  • 20,445
  • 9
  • 73
  • 162

1 Answers1

4

You'll need to tell the compiler that allocate is a template, otherwise the expression would be ambiguous:

pool.template allocate<T>(n, hint)

For the explanation, see Where and why do I have to put the “template” and “typename” keywords?.

The basic problem is that without template to tell the compiler that allocate is a template, the expression could be interpreted in different ways. That is, the expression is ambiguous. To see how, take a look at the following example:

struct my_pool {
    int allocate = 0; // allocate is a data member, not a template!
};

template <typename Pool>
void foo() {
    Pool pool;
    int T = 0, n = 0, hint = 0;
    pool.allocate<T>(n, hint); // *
}

int main() {
    foo<my_pool>();
}

The line I've marked with an asterisk has exactly the same expression as you had but it means something completely different. It's actually equivalent to (pool.allocate < T) > (n, hint). That is, the < and > aren't template argument delimeters any more - they're relational operators! I'm comparing the data member pool.allocate with T.

Community
  • 1
  • 1
Joseph Mansfield
  • 100,738
  • 18
  • 225
  • 303
  • I have never ever seen this syntax in my life. template following dot operator.. :o. Thank you. This solved my problem. I'll accept this answer as soon as it lets me. I bookmarked the link you gave me as well. – Brandon Jan 01 '14 at 12:31
  • @CantChooseUsernames I added an example to demonstrate why that expression is ambiguous. – Joseph Mansfield Jan 01 '14 at 12:39