2017-02-11 2 views
1

Я пытаюсь написать простой манекен аллокатора для vector<>, так что я могу использовать vector<> в качестве обертки для массивов стеки, например, так:Проблемы написанием пользовательского манекена аллокатора для вектора в C++

#include <vector> 
#include "stdio.h" 
#include "stack_allocator.h" 

using namespace std; 

int main() { 
    int buffer[100]; 
    vector<int, StackAllocator<int>> v((StackAllocator<int>(buffer, 100))); 
    v.push_back(2); 
    printf("%d", v[0]); 
    v.pop_back(); 
} 

я написал StackAllocator класса, но я получаю ошибки компоновщика в Visual Studio, которые, к сожалению, довольно общие:

1> main.cpp 
1> main.obj: error LNK2001: unresolved external symbol "public: void __cdecl std::StackAllocator<int,class std::allocator<int> >::destroy<int>(int *)" ([email protected]@[email protected][email protected]@[email protected]@@[email protected]@[email protected]) 
1> main.obj: error LNK2001: unresolved external symbol "public: void __cdecl std::StackAllocator<int,class std::allocator<int> >::construct<int,int>(int *,int &&)" ([email protected]@[email protected][email protected]@[email protected]@@[email protected]@[email protected]) 
1> main.obj: error LNK2001: unresolved external symbol "public: unsigned __int64 __cdecl std::StackAllocator<int,class std::allocator<int> >::max_size(void)const " ([email protected][email protected][email protected]@[email protected]@@[email protected]@QEBA_KXZ) 
1> main.obj: error LNK2001: unresolved external symbol "public: void __cdecl std::StackAllocator<int,class std::allocator<int> >::deallocate(int *,unsigned __int64)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected]) 
1> main.obj: error LNK2001: unresolved external symbol "public: int * __cdecl std::StackAllocator<int,class std::allocator<int> >::allocate(unsigned __int64,void const *)" ([email protected][email protected][email protected]@[email protected]@@[email protected]@[email protected]) 
1> main.obj: error LNK2001: unresolved external symbol "public: __cdecl std::StackAllocator<int,class std::allocator<int> >::StackAllocator<int,class std::allocator<int> >(int *,unsigned __int64,class std::allocator<int> const &)" ([email protected][email protected]@[email protected]@@[email protected]@[email protected][email protected]@[email protected]@Z) 
1> C:\Users\mathu\Desktop\StackVector\x64\Release\StackVector.exe : fatal error LNK1120: 6 unresolved externals 

Вот мой код:

stack_allocator.h:

#pragma once 

#include <functional> 

namespace std { 
    template <typename T, typename Allocator = std::allocator<T>> 
    class StackAllocator { 
    public: 
     typedef typename allocator_traits<Allocator>::value_type value_type; 
     typedef typename allocator_traits<Allocator>::pointer pointer; 
     typedef typename allocator_traits<Allocator>::const_pointer const_pointer; 
     typedef typename allocator_traits<Allocator>::size_type size_type; 
     typedef typename allocator_traits<Allocator>::difference_type difference_type; 
     typedef typename allocator_traits<Allocator>::const_void_pointer const_void_pointer; 
     typedef typename Allocator::reference reference; 
     typedef typename Allocator::const_reference const_reference; 

     template<typename T2> 
     struct rebind { 
      typedef StackAllocator<T2> other; 
     }; 

    private: 
     size_t m_size; 
     Allocator m_allocator; 
     pointer m_begin; 
     pointer m_end; 
     pointer m_stack_pointer; 

     bool pointer_to_internal_buffer(const_pointer p) const; 

    public: 
     StackAllocator(const Allocator& alloc = Allocator()); 
     StackAllocator(pointer buffer, size_t size, const Allocator& alloc = Allocator()); 
     template <typename T2> 
     StackAllocator(const StackAllocator<T2, Allocator>& other); 
     pointer allocate(size_type n, const_void_pointer hint = const_void_pointer()); 
     void deallocate(pointer p, size_type n); 
     size_type capacity() const; 
     size_type max_size() const noexcept; 
     pointer address(reference x) const noexcept; 
     const_pointer address(const_reference x) const noexcept; 
     pointer buffer() const noexcept; 

     template <typename T2, typename... Args> 
     void construct(T2* p, Args&&... args); 

     template <typename T2> 
     void destroy(T2* p); 

     template <typename T2> 
     bool operator==(const StackAllocator<T2, Allocator>& other) const noexcept; 

     template <typename T2> 
     bool operator!=(const StackAllocator<T2, Allocator>& other) const noexcept; 
    }; 
} 

stack_allocator.cpp:

#include "stack_allocator.h" 

namespace std { 
#define AllocatorTemplate template <typename T, typename Allocator> 
#define StackAlloc StackAllocator<T, Allocator> 

    AllocatorTemplate StackAlloc::StackAllocator(const Allocator& alloc) : 
     m_size(0), 
     m_allocator(alloc), 
     m_begin(nullptr), 
     m_end(nullptr), 
     m_stack_pointer(nullptr) { 
    } 

    AllocatorTemplate StackAlloc::StackAllocator(pointer buffer, size_t size, const Allocator& alloc) : 
     m_size(size), 
     m_allocator(alloc), 
     m_begin(buffer), 
     m_end(buffer + size), 
     m_stack_pointer(buffer) { 
    } 

    AllocatorTemplate template <typename T2> StackAlloc::StackAllocator(const StackAllocator<T2, Allocator>& other) : 
     m_size(other.m_size), 
     m_allocator(other.m_allocator), 
     m_begin(other.m_begin), 
     m_end(other.m_end), 
     m_stack_pointer(other.m_stack_pointer) { 
    } 

    AllocatorTemplate typename StackAlloc::size_type StackAlloc::capacity() const { 
     return m_size; 
    } 

    AllocatorTemplate typename StackAlloc::pointer StackAlloc::allocate(size_type n, const_void_pointer hint) { 
     if (n <= size_type(distance(m_stack_pointer, m_end))) { 
      pointer result = m_stack_pointer; 
      m_stack_pointer += n; 
      return result; 
     } 
     else 
      return m_allocator.allocate(n, hint); 
    } 

    AllocatorTemplate void StackAlloc::deallocate(pointer p, size_type n) { 
     if (pointer_to_internal_buffer(p)) 
      m_stack_pointer -= n; 
     else 
      m_allocator.deallocate(p, n); 
    } 

    AllocatorTemplate typename StackAlloc::size_type StackAlloc::max_size() const noexcept { 
     return m_size(); 
    } 

    AllocatorTemplate template <typename T2, typename... Args> void StackAlloc::construct(T2* p, Args&&... args) { 
     m_allocator.construct(p, forward<Args>(args)...); 
    } 

    AllocatorTemplate template <typename T2> void StackAlloc::destroy(T2* p) { 
     m_allocator.destroy(p); 
    } 

    AllocatorTemplate typename StackAlloc::pointer StackAlloc::address(reference x) const noexcept { 
     if (pointer_to_internal_buffer(addressof(x))) 
      return addressof(x); 
     else 
      return m_allocator.address(x); 
    } 

    AllocatorTemplate typename StackAlloc::const_pointer StackAlloc::address(const_reference x) const noexcept { 
     if (pointer_to_internal_buffer(addressof(x))) 
      return addressof(x); 
     else 
      return m_allocator.address(x); 
    } 

    AllocatorTemplate typename StackAlloc::pointer StackAlloc::buffer() const noexcept { 
     return m_begin; 
    } 

    AllocatorTemplate bool StackAlloc::pointer_to_internal_buffer(const_pointer p) const { 
     return (!(less<const_pointer>()(p, m_begin)) && (less<const_pointer>()(p, m_end))); 
    } 

    AllocatorTemplate template <typename T2> bool StackAlloc::operator==(const StackAllocator<T2, Allocator>& other) const noexcept { 
     return buffer() == other.buffer(); 
    } 

    AllocatorTemplate template <typename T2> bool StackAlloc::operator!=(const StackAllocator<T2, Allocator>& other) const noexcept { 
     return buffer() != other.buffer(); 
    } 
} 

Я извиняюсь за размещение много кода, но я действительно понятия не имею, где этот вопрос может быть. Кто-нибудь может понять, что случилось?

+0

Хотя это интересное упражнение, интересно, есть ли у него какие-либо преимущества в сравнении с использованием только 'std :: array '. –

+0

Существует, так как после того, как я его работаю, я планирую сделать его поддержкой массивов переменной длины, созданных в стеке, с помощью alloca(), поэтому я избегал делать размер постоянной времени компиляции. –

+0

VLAs поддерживаются GCC на C++ в качестве расширения. Они не являются стандартными C++. –

ответ