In my experiments with scoped_allocator_adaptor, I'm trying to pass the allocator obtained from main(..) into S1's constructor (more generally there would be multiple different types within S1 that would all use the allocator that was made available in the constructor). However, I get the compile error below indicating that the allocator should be default constructible. Can someone help explain why this might be the case? Is there some conversion taking place leading to the default constructed version of the allocator being needed?
#include <iostream>
#include <cassert>
#include <vector>
#include <scoped_allocator>
// Move allocator and container aliases into namepsace
namespace custom
{
template <typename T>
struct MyAlloc
{
using value_type = T;
MyAlloc(const std::string &scope) noexcept : _scope(scope) {}
// Rebinding allocatos to different type
template <class U>
MyAlloc(const MyAlloc<U> & other) noexcept : _scope(other._scope) {}
// Allow for move operations to be noexcept
//using is_always_equal = std::true_type;
value_type* allocate(std::size_t n) noexcept
{
std::cout << "Allocating " << n << " objects within " << _scope << " from " << __PRETTY_FUNCTION__ << std::endl;
return static_cast<value_type*>(::operator new (n*sizeof(value_type)));
}
void deallocate(value_type* p, std::size_t n) noexcept
{
std::cout << "Deallocating " << n << " objects within " << _scope << " from " << __PRETTY_FUNCTION__ << std::endl;
::operator delete(p);
}
std::string _scope;
};
// Allocators compare equal to enable one allocator to de-allocate memory
// from another
template <typename T>
bool operator==(const MyAlloc<T> &x1, const MyAlloc<T> &x2) noexcept
{
return true;
}
template <typename T>
bool operator!=(const MyAlloc<T> &x1, const MyAlloc<T> &x2) noexcept
{
return !(x1 == x2);
}
template <typename T>
using allocator = std::scoped_allocator_adaptor<MyAlloc<T>>;
template <typename T> // adaptor to propagate
using vector = std::vector<T, allocator<T>>;
template <typename T>
using bstr = std::basic_string<T, std::char_traits<T>, allocator<T>>;
using string = bstr<char>;
}
struct S1
{
using allocator_type = custom::allocator<std::byte>;
S1(allocator_type alloc) : str("This is a very long string indeed..", std::allocator_traits<allocator_type>::rebind_alloc<char>(alloc))
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
S1(const S1 &other, allocator_type al) : str(other.str, std::allocator_traits<allocator_type>::rebind_alloc<char>(al))
{
std::cout << __PRETTY_FUNCTION__ << std::endl;
}
custom::string str;
};
int main()
{
custom::allocator<std::byte> sc{"scope"};
custom::vector<S1> cv{sc};
// cv.emplace_back();
}
Compile error:
/usr/include/c++/10/scoped_allocator: In instantiation of ‘std::scoped_allocator_adaptor<_OuterAlloc, _InnerAllocs>::scoped_allocator_adaptor() [with _OuterAlloc = custom::MyAlloc<S1>; _InnerAllocs = {}]’:
/usr/include/c++/10/bits/stl_vector.h:626:35: required from here
/usr/include/c++/10/scoped_allocator:304:60: error: no matching function for call to ‘custom::MyAlloc<S1>::MyAlloc()’
304 | scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { }
| ^
d2.cc:17:9: note: candidate: ‘template<class U> custom::MyAlloc<T>::MyAlloc(const custom::MyAlloc<U>&) [with U = U; T = S1]’
17 | MyAlloc(const MyAlloc<U> & other) noexcept : _scope(other._scope) {}
| ^~~~~~~
d2.cc:17:9: note: template argument deduction/substitution failed:
In file included from d2.cc:4:
/usr/include/c++/10/scoped_allocator:304:60: note: candidate expects 1 argument, 0 provided
304 | scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { }
| ^
d2.cc:13:9: note: candidate: ‘custom::MyAlloc<T>::MyAlloc(const string&) [with T = S1; std::string = std::__cxx11::basic_string<char>]’
13 | MyAlloc(const std::string &scope) noexcept : _scope(scope) {}
| ^~~~~~~
d2.cc:13:9: note: candidate expects 1 argument, 0 provided
d2.cc:10:12: note: candidate: ‘custom::MyAlloc<S1>::MyAlloc(const custom::MyAlloc<S1>&)’
10 | struct MyAlloc
| ^~~~~~~
d2.cc:10:12: note: candidate expects 1 argument, 0 provided
d2.cc:10:12: note: candidate: ‘custom::MyAlloc<S1>::MyAlloc(custom::MyAlloc<S1>&&)’
d2.cc:10:12: note: candidate expects 1 argument, 0 provided
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…