Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
174 views
in Technique[技术] by (71.8m points)

c++ - scoped_allocator_adaptor seems to require allocator to be default constructed

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This line: custom::vector<S1> cv{sc}; is the problem.

Because you've used brackets, it's trying to call vectors initializer-list constructor, which has an optional parameter which is an allocator - which it default constructs.

See the last two constructors in the list on cppreference

If you change that line to custom::vector<S1> cv(sc); it will compile w/o error.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...