mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 02:33:06 +01:00
Allow incomplete template types in unique_function arguments
We can't declare unique_function that has in its arguments a reference to a template type with an incomplete argument. For instance, we can't declare unique_function<void(SmallVectorImpl<A>&)> when A is forward declared. This is because SFINAE will trigger a hard error in this case, when instantiating IsSizeLessThanThresholdT with the incomplete type. This patch specialize AdjustedParamT for references to remove this error. Committed on behalf of: @math-fehr (Fehr Mathieu) Reviewed By: DaniilSuchkov, yrouban
This commit is contained in:
parent
f79eaab45a
commit
ebb8c67ccd
@ -90,13 +90,24 @@ protected:
|
||||
// The heuristic used is related to common ABI register passing conventions.
|
||||
// It doesn't have to be exact though, and in one way it is more strict
|
||||
// because we want to still be able to observe either moves *or* copies.
|
||||
template <typename T> struct AdjustedParamTBase {
|
||||
static_assert(!std::is_reference<T>::value,
|
||||
"references should be handled by template specialization");
|
||||
using type = typename std::conditional<
|
||||
llvm::is_trivially_copy_constructible<T>::value &&
|
||||
llvm::is_trivially_move_constructible<T>::value &&
|
||||
IsSizeLessThanThresholdT<T>::value,
|
||||
T, T &>::type;
|
||||
};
|
||||
|
||||
// This specialization ensures that 'AdjustedParam<V<T>&>' or
|
||||
// 'AdjustedParam<V<T>&&>' does not trigger a compile-time error when 'T' is
|
||||
// an incomplete type and V a templated type.
|
||||
template <typename T> struct AdjustedParamTBase<T &> { using type = T &; };
|
||||
template <typename T> struct AdjustedParamTBase<T &&> { using type = T &; };
|
||||
|
||||
template <typename T>
|
||||
using AdjustedParamT = typename std::conditional<
|
||||
!std::is_reference<T>::value &&
|
||||
llvm::is_trivially_copy_constructible<T>::value &&
|
||||
llvm::is_trivially_move_constructible<T>::value &&
|
||||
IsSizeLessThanThresholdT<T>::value,
|
||||
T, T &>::type;
|
||||
using AdjustedParamT = typename AdjustedParamTBase<T>::type;
|
||||
|
||||
// The type of the erased function pointer we use as a callback to dispatch to
|
||||
// the stored callable when it is trivial to move and destroy.
|
||||
|
@ -273,4 +273,22 @@ TEST(UniqueFunctionTest, SFINAE) {
|
||||
EXPECT_EQ("string", returns([] { return "hello"; }));
|
||||
}
|
||||
|
||||
// A forward declared type, and a templated type.
|
||||
class Incomplete;
|
||||
template <typename T> class Templated { T A; };
|
||||
|
||||
// Check that we can define unique_function that have references to
|
||||
// incomplete types, even if those types are templated over an
|
||||
// incomplete type.
|
||||
TEST(UniqueFunctionTest, IncompleteTypes) {
|
||||
unique_function<void(Templated<Incomplete> &&)>
|
||||
IncompleteArgumentRValueReference;
|
||||
unique_function<void(Templated<Incomplete> &)>
|
||||
IncompleteArgumentLValueReference;
|
||||
unique_function<void(Templated<Incomplete> *)> IncompleteArgumentPointer;
|
||||
unique_function<Templated<Incomplete> &()> IncompleteResultLValueReference;
|
||||
unique_function<Templated<Incomplete> && ()> IncompleteResultRValueReference2;
|
||||
unique_function<Templated<Incomplete> *()> IncompleteResultPointer;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
Loading…
Reference in New Issue
Block a user