Я всегда получаю ожидаемое первичное выражение при попытке передать параметр шаблона вызову функции.
Моя ошибка выглядит так:
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
Мой код выглядит так:
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.
}
Ошибки происходят, когда PtrAllocator::allocate
вызовы Pool::allocate
PtrAllocator::allocate
. То же самое происходит с max_size
но не происходит deallocate
. Любые идеи, почему это не позволит мне указать параметр шаблона?
Вам нужно сообщить компилятору, что allocate
является шаблоном, иначе выражение будет неоднозначным:
pool.template allocate<T>(n, hint)
Объяснение см. В разделе Где и почему я должен поставить ключевые слова "шаблон" и "имя-тип"? ,
Основная проблема заключается в том, что без template
указать компилятору, который allocate
шаблон, выражение может интерпретироваться по-разному. То есть выражение неоднозначно. Чтобы узнать, как это сделать, взгляните на следующий пример:
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>();
}
Строка, отмеченная звездочкой, имеет то же выражение, что и у вас, но это означает нечто совершенно другое. Это фактически эквивалентно (pool.allocate < T) > (n, hint)
. То есть, <
и >
больше не являются параметрами шаблонов аргументов - они являются реляционными операторами! Я сравниваю pool.allocate
данных pool.allocate
с T