Make forward-declaring bssl::UniquePtr<T> actually work.
The compiler complains about: error: explicit specialization of 'bssl::internal::Deleter<evp_pkey_st>' after instantiation This is because, although the deleter's operator() is not instantiated without emitting std::unique_ptr's destructor, the deleter itself *is*. Deleters are allowed to have non-zero size, so a std::unique_ptr actually embeds a copy of the deleter, so it needs the size of the deleter. As with all problems in computer science, we fix this with a layer of indirection. Instead of specializing the deleter, we specialize bssl::internal::DeleterImpl which, when specialized, has a static method Free. That is only instantiated inside bssl::internal::Deleter::operator(), giving us the desired properties. (Did I mention forward decls are terrible? I wish people wouldn't want them so much.) Also appease clang-format. Change-Id: I9a07b2fd13e8bdfbd204e225ac72c52d20a397dc Reviewed-on: https://boringssl-review.googlesource.com/10964 Reviewed-by: Matt Braithwaite <mab@google.com> Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
committed by
CQ bot account: commit-bot@chromium.org
parent
934b57e8c9
commit
4709203de6
+30
-12
@@ -335,7 +335,23 @@ namespace bssl {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class T> struct Deleter {};
|
||||
template <typename T>
|
||||
struct DeleterImpl {};
|
||||
|
||||
template <typename T>
|
||||
struct Deleter {
|
||||
void operator()(T *ptr) {
|
||||
// Rather than specialize Deleter for each type, we specialize
|
||||
// DeleterImpl. This allows bssl::UniquePtr<T> to be used while only
|
||||
// including base.h as long as the destructor is not emitted. This matches
|
||||
// std::unique_ptr's behavior on forward-declared types.
|
||||
//
|
||||
// DeleterImpl itself is specialized in the corresponding module's header
|
||||
// and must be included to release an object. If not included, the compiler
|
||||
// will error that DeleterImpl<T> does not have a method Free.
|
||||
DeleterImpl<T>::Free(ptr);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename CleanupRet, void (*init)(T *),
|
||||
CleanupRet (*cleanup)(T *)>
|
||||
@@ -358,22 +374,24 @@ class StackAllocated {
|
||||
|
||||
} // namespace internal
|
||||
|
||||
#define BORINGSSL_MAKE_DELETER(type, deleter) \
|
||||
namespace internal { \
|
||||
template <> struct Deleter<type> { \
|
||||
void operator()(type* ptr) { deleter(ptr); } \
|
||||
}; \
|
||||
#define BORINGSSL_MAKE_DELETER(type, deleter) \
|
||||
namespace internal { \
|
||||
template <> \
|
||||
struct DeleterImpl<type> { \
|
||||
static void Free(type *ptr) { deleter(ptr); } \
|
||||
}; \
|
||||
}
|
||||
|
||||
// This makes a unique_ptr to STACK_OF(type) that owns all elements on the
|
||||
// stack, i.e. it uses sk_pop_free() to clean up.
|
||||
#define BORINGSSL_MAKE_STACK_DELETER(type, deleter) \
|
||||
#define BORINGSSL_MAKE_STACK_DELETER(type, deleter) \
|
||||
namespace internal { \
|
||||
template <> struct Deleter<STACK_OF(type)> { \
|
||||
void operator()(STACK_OF(type)* ptr) { \
|
||||
sk_##type##_pop_free(ptr, deleter); \
|
||||
} \
|
||||
}; \
|
||||
template <> \
|
||||
struct DeleterImpl<STACK_OF(type)> { \
|
||||
static void Free(STACK_OF(type) *ptr) { \
|
||||
sk_##type##_pop_free(ptr, deleter); \
|
||||
} \
|
||||
}; \
|
||||
}
|
||||
|
||||
// Holds ownership of heap-allocated BoringSSL structures. Sample usage:
|
||||
|
||||
Reference in New Issue
Block a user