어떤 상황에서는 기본 할당자를 템플릿 유형으로 받아들이고 allocate()
및 deallocate()
호출을 기본 할당 자 멤버로 전달하는 것 외에는 아무것도하지 않는 할당자를 작성하고 있습니다. std::vector
이 사용자 지정 할당 자로 s를 만들면 잘 작동합니다. 기본적으로 사용할 래퍼를 작성 했지만 성공하지 못했습니다. make_shared
dummy_allocator<T, std::allocator<T>>
다음은 재현 가능한 예입니다.
#include <memory>
namespace test {
template<typename T, typename base_allocator=std::allocator<T>>
class dummy_allocator {
public:
typedef typename std::allocator_traits<base_allocator>::size_type size_type;
typedef typename std::allocator_traits<base_allocator>::difference_type difference_type;
typedef typename std::allocator_traits<base_allocator>::pointer pointer;
typedef typename std::allocator_traits<base_allocator>::const_pointer const_pointer;
typedef typename std::allocator_traits<base_allocator>::value_type value_type;
template<class U>
struct rebind {
typedef dummy_allocator<U,
typename std::allocator_traits<base_allocator>::template rebind_alloc<U>> other;
};
template<typename... Args>
dummy_allocator(Args &&... args) noexcept : alloc(std::forward<Args>(args)...) {}
dummy_allocator(const dummy_allocator& a) = default;
[[nodiscard]] T *allocate(std::size_t n) {
T *p = alloc.allocate(n);
return p;
}
void deallocate(T *p, std::size_t size) noexcept {
alloc.deallocate(p, size);
}
private:
base_allocator alloc;
};
/// Allocate using a wrapped version of passed in allocator
template <typename T, typename Alloc, typename... Args>
std::shared_ptr<T> allocate_shared(const Alloc& alloc, Args&&... args) {
auto dummy_alloc = dummy_allocator<T, Alloc>(alloc);
return std::allocate_shared<T>(dummy_alloc, std::forward<Args>(args)...);
}
/// Create a shared pointer from a default stl allocator wrapped in profile allocator.
template <typename T, typename... Args>
std::shared_ptr<T> make_shared(Args&&... args) {
return test::allocate_shared<T>(std::allocator<T>(), std::forward<Args>(args)...);
}
} // namespace test
int main() {
auto ptr = test::make_shared<double>();
return 0;
}
위의 코드를 실행했을 때 컴파일러가 몇 가지 기이 한 템플릿 대체 실패 오류를 생성했습니다.
/usr/include/c++/10.1.0/bits/shared_ptr_base.h:679:43: required from ‘std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...) [with _Tp = double; _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10.1.0/bits/shared_ptr_base.h:1371:71: required from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}; _Tp = double; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10.1.0/bits/shared_ptr.h:408:59: required from ‘std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}; _Tp = double]’
/usr/include/c++/10.1.0/bits/shared_ptr.h:859:14: required from ‘std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = double; _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}]’
/home/ray/home/testing/src/alloc.cpp:44:35: required from ‘std::shared_ptr<_Tp> test::allocate_shared(const Alloc&, Args&& ...) [with T = double; Alloc = std::allocator<double>; Args = {}]’
/home/ray/home/testing/src/alloc.cpp:50:36: required from ‘std::shared_ptr<_Tp> test::make_shared(Args&& ...) [with T = double; Args = {}]’
/home/ray/home/testing/src/alloc.cpp:86:46: required from here
/home/ray/home/testing/src/alloc.cpp:25:82: error: no matching function for call to ‘std::allocator<std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic> >::allocator(const test::dummy_allocator<double, std::allocator<double> >&)’
25 | dummy_allocator(Args &&... args) noexcept : alloc(std::forward<Args>(args)...) {}
| ^
In file included from /usr/include/c++/10.1.0/list:61,
from /home/ray/home/testing/src/alloc.cpp:3:
/usr/include/c++/10.1.0/bits/allocator.h:157:2: note: candidate: ‘template<class _Tp1> constexpr std::allocator< <template-parameter-1-1> >::allocator(const std::allocator<_Tp1>&) [with _Tp1 = _Tp1; _Tp = std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic>]’
157 | allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { }
| ^~~~~~~~~
/usr/include/c++/10.1.0/bits/allocator.h:157:2: note: template argument deduction/substitution failed:
/home/ray/home/testing/src/alloc.cpp:25:82: note: ‘const test::dummy_allocator<double, std::allocator<double> >’ is not derived from ‘const std::allocator<_Up>’
25 | dummy_allocator(Args &&... args) noexcept : alloc(std::forward<Args>(args)...) {}
| ^
In file included from /usr/include/c++/10.1.0/list:61,
from /home/ray/home/testing/src/alloc.cpp:3:
/usr/include/c++/10.1.0/bits/allocator.h:147:7: note: candidate: ‘constexpr std::allocator< <template-parameter-1-1> >::allocator(const std::allocator< <template-parameter-1-1> >&) [with _Tp = std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic>]’
147 | allocator(const allocator& __a) _GLIBCXX_NOTHROW
| ^~~~~~~~~
/usr/include/c++/10.1.0/bits/allocator.h:147:34: note: no known conversion for argument 1 from ‘const test::dummy_allocator<double, std::allocator<double> >’ to ‘const std::allocator<std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic> >&’
147 | allocator(const allocator& __a) _GLIBCXX_NOTHROW
| ~~~~~~~~~~~~~~~~~^~~
/usr/include/c++/10.1.0/bits/allocator.h:144:7: note: candidate: ‘constexpr std::allocator< <template-parameter-1-1> >::allocator() [with _Tp = std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic>]’
144 | allocator() _GLIBCXX_NOTHROW { }
| ^~~~~~~~~
/usr/include/c++/10.1.0/bits/allocator.h:144:7: note: candidate expects 0 arguments, 1 provided
... (The above error basically is repeated 2 more times)
특히이 오류는 발생하는 문제를 나타내는 것으로 보입니다.
error: no matching function for call to ‘std::allocator<std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic> >::allocator(const test::dummy_allocator<double, std::allocator<double> >&)’
기본적으로 "의 생성자에서의 생성자 dummy_allocator
에 a dummy_allocator
를 전달할 수 없습니다. "라고 말하는 경우 std::allocator
. 하지만 나는 그렇게하지 않습니다. 에서가 allocate_shared
, 내가 전달하고있어 std::allocator
에 dummy_allocator
.
나는 컴파일러 오류를 읽고 머리를 긁적이지만 내가 뭘 잘못하고 있는지에 대한 결론을 내리지 못했습니다. 어떤 도움이라도 대단히 감사하겠습니다!
편집 : 나는 마술 shared_ptr이 무엇을하든간에 내 dummy_allocator의 복사 생성자를 시도하고 있으며 완벽한 전달은 실제 복사 생성자 대신 복사 구성을 캡처한다는 직감이 있다고 생각합니다. 그러나, 나는이 없다 더 는 가변 인수 템플릿의로이 문제를 해결하기 위해 내가 사용하지 수있는 방법을 생각 std::is_same<Args, dummy_allocator>
a는 완벽한 전달 생성자에서 절을 필요로한다.
따라서 Daniel Langr가 지적했듯이 dummy_allocator를 생성하는 복사 만 실패합니다. 다음 require 절을 사용하여 문제를 해결했습니다.
...
template <typename T1, typename ...TV>
struct is_dummy : std::is_same<typename std::decay<T1>::type, dummy_allocator<T, base_allocator>>{
};
template<typename... Args>
requires (!is_dummy<Args...>::value)
dummy_allocator(Args &&... args) noexcept : alloc(std::forward<Args>(args)...) {}
dummy_allocator() = default;
dummy_allocator(const dummy_allocator& a) = default;
...
그러나 shared_ptr
오류가 조금 더 긴 문제 를 해결하기에 충분하지 않습니다 ... *
따라서 다음과 같은 오류가 발생합니다.
#include <memory>
namespace test {
template<typename T, typename base_allocator=std::allocator<T>>
class dummy_allocator {
public:
/// Necessary for allocators, propagate exactly what the base_allocator
/// wants.
typedef typename std::allocator_traits<base_allocator>::size_type size_type;
typedef typename std::allocator_traits<base_allocator>::difference_type difference_type;
typedef typename std::allocator_traits<base_allocator>::pointer pointer;
typedef typename std::allocator_traits<base_allocator>::const_pointer const_pointer;
typedef typename std::allocator_traits<base_allocator>::value_type value_type;
template<class U>
struct rebind {
typedef dummy_allocator<U,
typename std::allocator_traits<base_allocator>::template rebind_alloc<U>> other;
};
template <typename T1, typename ...TV>
struct is_dummy : std::is_same<typename std::decay<T1>::type, dummy_allocator<T, base_allocator>>{
};
template<typename... Args>
requires (!is_dummy<Args...>::value)
dummy_allocator(Args &&... args) noexcept : alloc(std::forward<Args>(args)...) {}
dummy_allocator() = default;
dummy_allocator(const dummy_allocator& a) = default;
[[nodiscard]] T *allocate(std::size_t n) {
T *p = alloc.allocate(n);
return p;
}
void deallocate(T *p, std::size_t size) noexcept {
alloc.deallocate(p, size);
}
private:
base_allocator alloc;
};
/// Allocate using a wrapped version of passed in allocator
template <typename T, typename Alloc, typename... Args>
auto allocate_shared(const Alloc& alloc, Args&&... args) {
auto dummy_alloc = dummy_allocator<T, Alloc>(alloc);
return std::allocate_shared<T>(dummy_alloc, std::forward<Args>(args)...);
}
/// Create a shared pointer from a default stl allocator wrapped in profile allocator.
template <typename T, typename... Args>
auto make_shared(Args&&... args) {
return test::allocate_shared<T>(std::allocator<T>(), std::forward<Args>(args)...);
}
} // namespace test
int main() {
// This will fail
auto ptr = test::make_shared<double>();
// This will now work
auto dummy_alloc = test::dummy_allocator<int, std::allocator<int>>();
auto dummy_alloc2 = test::dummy_allocator<int, std::allocator<int>>(dummy_alloc);
return 0;
}
관련 오류 :
/usr/include/c++/10.1.0/bits/shared_ptr_base.h:679:43: required from ‘std::__shared_count<_Lp>::__shared_count(_Tp*&, std::_Sp_alloc_shared_tag<_Alloc>, _Args&& ...) [with _Tp = double; _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10.1.0/bits/shared_ptr_base.h:1371:71: required from ‘std::__shared_ptr<_Tp, _Lp>::__shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}; _Tp = double; __gnu_cxx::_Lock_policy _Lp = __gnu_cxx::_S_atomic]’
/usr/include/c++/10.1.0/bits/shared_ptr.h:408:59: required from ‘std::shared_ptr<_Tp>::shared_ptr(std::_Sp_alloc_shared_tag<_Tp>, _Args&& ...) [with _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}; _Tp = double]’
/usr/include/c++/10.1.0/bits/shared_ptr.h:859:14: required from ‘std::shared_ptr<_Tp> std::allocate_shared(const _Alloc&, _Args&& ...) [with _Tp = double; _Alloc = test::dummy_allocator<double, std::allocator<double> >; _Args = {}]’
/home/ray/home/test/src/alloc.cpp:53:35: required from ‘auto test::allocate_shared(const Alloc&, Args&& ...) [with T = double; Alloc = std::allocator<double>; Args = {}]’
/home/ray/home/test/src/alloc.cpp:59:36: required from ‘auto test::make_shared(Args&& ...) [with T = double; Args = {}]’
/home/ray/home/test/src/alloc.cpp:95:46: required from here
/home/ray/home/test/src/alloc.cpp:31:82: error: no matching function for call to ‘std::allocator<std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic> >::allocator(const test::dummy_allocator<double, std::allocator<double> >&)’
31 | dummy_allocator(Args &&... args) noexcept : alloc(std::forward<Args>(args)...) {}
| ^
In file included from /usr/include/c++/10.1.0/list:61,
from /home/ray/home/test/src/alloc.cpp:3:
/usr/include/c++/10.1.0/bits/allocator.h:157:2: note: candidate: ‘template<class _Tp1> constexpr std::allocator< <template-parameter-1-1> >::allocator(const std::allocator<_Tp1>&) [with _Tp1 = _Tp1; _Tp = std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic>]’
157 | allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { }
| ^~~~~~~~~
/usr/include/c++/10.1.0/bits/allocator.h:157:2: note: template argument deduction/substitution failed:
/home/ray/home/test/src/alloc.cpp:31:82: note: ‘const test::dummy_allocator<double, std::allocator<double> >’ is not derived from ‘const std::allocator<_Up>’
31 | dummy_allocator(Args &&... args) noexcept : alloc(std::forward<Args>(args)...) {}
| ^
In file included from /usr/include/c++/10.1.0/list:61,
from /home/ray/home/test/src/alloc.cpp:3:
/usr/include/c++/10.1.0/bits/allocator.h:147:7: note: candidate: ‘constexpr std::allocator< <template-parameter-1-1> >::allocator(const std::allocator< <template-parameter-1-1> >&) [with _Tp = std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic>]’
147 | allocator(const allocator& __a) _GLIBCXX_NOTHROW
| ^~~~~~~~~
/usr/include/c++/10.1.0/bits/allocator.h:147:34: note: no known conversion for argument 1 from ‘const test::dummy_allocator<double, std::allocator<double> >’ to ‘const std::allocator<std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic> >&’
147 | allocator(const allocator& __a) _GLIBCXX_NOTHROW
| ~~~~~~~~~~~~~~~~~^~~
/usr/include/c++/10.1.0/bits/allocator.h:144:7: note: candidate: ‘constexpr std::allocator< <template-parameter-1-1> >::allocator() [with _Tp = std::_Sp_counted_ptr_inplace<double, test::dummy_allocator<double, std::allocator<double> >, __gnu_cxx::_S_atomic>]’
144 | allocator() _GLIBCXX_NOTHROW { }
| ^~~~~~~~~
/usr/include/c++/10.1.0/bits/allocator.h:144:7: note: candidate expects 0 arguments, 1 provided
가변 생성자를 제거하고 다음 두 가지를 추가하기 만하면됩니다.
dummy_allocator(const base_allocator& a) : alloc(a)
{}
template<class U, class Alloc>
dummy_allocator(const dummy_allocator<U, Alloc>& a) : alloc(a.alloc)
{}
인수가 필요한 할당 자에게 인수를 전달하려는 경우 문제가 해결되지 않습니다.
그런 다음 사용할 수 있습니다 std::is_constructible
.
template<class... Args>
dummy_allocator(Args&&... args)
requires(std::is_constructible_v<base_allocator, Args...>)
: alloc(std::forward<Args>(args)...)
{}
template<class U, class Alloc>
dummy_allocator(const dummy_allocator<U, Alloc>& a) : alloc(a.alloc)
{}
리 바인딩 된 할당 자 유형에 대해 잘 구성되어야template<class U, class Alloc> dummy_allocator
하므로 두 경우 모두 constuctor가 필요 합니다.dummy_allocator a(b)
b
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다