mirror of
https://github.com/ETLCPP/etl.git
synced 2026-07-30 08:16:19 +08:00
Only enable the assign and insert member functions for class ivector<… (#1467)
* Only enable the assign and insert member functions for class ivector<T*> & class ivector<const T*> when the value_type the iterator references is a pointer to T. * Imporoved enable_if for assign and insert. * clang-format * std::void_t -> etl::void_t * Made enable_if condition into a common class struct --------- Co-authored-by: John Wellbelove <john.wellbelove@etlcpp.com>
This commit is contained in:
parent
04b7004110
commit
55429eddd2
@ -70,6 +70,13 @@ namespace etl
|
||||
|
||||
typedef pvoidvector base_t;
|
||||
|
||||
template <typename TIterator>
|
||||
struct is_compatible_iterator
|
||||
: etl::integral_constant<bool, etl::is_pointer<typename etl::iterator_traits<TIterator>::value_type>::value
|
||||
&& etl::is_convertible<typename etl::iterator_traits<TIterator>::value_type, value_type>::value>
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//*********************************************************************
|
||||
@ -320,7 +327,7 @@ namespace etl
|
||||
///\param last The iterator to the last element + 1.
|
||||
//*********************************************************************
|
||||
template <typename TIterator>
|
||||
void assign(TIterator first, TIterator last)
|
||||
typename etl::enable_if< is_compatible_iterator<TIterator>::value, void>::type assign(TIterator first, TIterator last)
|
||||
{
|
||||
base_t::assign(first, last);
|
||||
}
|
||||
@ -440,8 +447,8 @@ namespace etl
|
||||
///\param first The first element to add.
|
||||
///\param last The last + 1 element to add.
|
||||
//*********************************************************************
|
||||
template <class TIterator>
|
||||
void insert(const_iterator position, TIterator first, TIterator last)
|
||||
template <typename TIterator>
|
||||
typename etl::enable_if< is_compatible_iterator<TIterator>::value, void>::type insert(const_iterator position, TIterator first, TIterator last)
|
||||
{
|
||||
base_t::insert(base_t::iterator(position), first, last);
|
||||
}
|
||||
@ -573,6 +580,13 @@ namespace etl
|
||||
|
||||
typedef pvoidvector base_t;
|
||||
|
||||
template <typename TIterator>
|
||||
struct is_compatible_iterator
|
||||
: etl::integral_constant<bool, etl::is_pointer<typename etl::iterator_traits<TIterator>::value_type>::value
|
||||
&& etl::is_convertible<typename etl::iterator_traits<TIterator>::value_type, value_type>::value>
|
||||
{
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
//*********************************************************************
|
||||
@ -823,7 +837,7 @@ namespace etl
|
||||
///\param last The iterator to the last element + 1.
|
||||
//*********************************************************************
|
||||
template <typename TIterator>
|
||||
void assign(TIterator first, TIterator last)
|
||||
typename etl::enable_if< is_compatible_iterator<TIterator>::value, void>::type assign(TIterator first, TIterator last)
|
||||
{
|
||||
base_t::assign(first, last);
|
||||
}
|
||||
@ -901,8 +915,8 @@ namespace etl
|
||||
///\param first The first element to add.
|
||||
///\param last The last + 1 element to add.
|
||||
//*********************************************************************
|
||||
template <class TIterator>
|
||||
void insert(const_iterator position, TIterator first, TIterator last)
|
||||
template <typename TIterator>
|
||||
typename etl::enable_if< is_compatible_iterator<TIterator>::value, void>::type insert(const_iterator position, TIterator first, TIterator last)
|
||||
{
|
||||
base_t::insert(base_t::iterator(position), first, last);
|
||||
}
|
||||
|
||||
@ -1683,5 +1683,48 @@ namespace
|
||||
CHECK(etl_data2.size() == swap_other_data.size());
|
||||
CHECK(etl_data2.max_size() == other_size);
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
template <typename TContainer, typename TIterator, typename = void>
|
||||
struct is_assign_callable : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TContainer, typename TIterator>
|
||||
struct is_assign_callable<TContainer, TIterator,
|
||||
etl::void_t<decltype(std::declval<TContainer&>().assign(std::declval<TIterator>(), std::declval<TIterator>()))>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TContainer, typename TIterator1, typename TIterator2, typename = void>
|
||||
struct is_insert_callable : std::false_type
|
||||
{
|
||||
};
|
||||
|
||||
template <typename TContainer, typename TIterator1, typename TIterator2>
|
||||
struct is_insert_callable<
|
||||
TContainer, TIterator1, TIterator2,
|
||||
etl::void_t<decltype(std::declval<TContainer&>().insert(std::declval<TIterator1>(), std::declval<TIterator2>(), std::declval<TIterator2>()))>>
|
||||
: std::true_type
|
||||
{
|
||||
};
|
||||
TEST_FIXTURE(SetupFixture, test_issue_1464_etl_vector_insert_allows_inserting_an_incompatible_type)
|
||||
{
|
||||
struct SomeStruct
|
||||
{
|
||||
int foo;
|
||||
};
|
||||
|
||||
using ContainerType = etl::vector<SomeStruct*, 4>;
|
||||
using Iterator1Type = etl::vector<SomeStruct*, 4>::iterator;
|
||||
using Iterator2Type = etl::vector<SomeStruct, 4>::const_iterator;
|
||||
|
||||
constexpr bool can_assign = is_assign_callable<ContainerType, Iterator2Type>::value;
|
||||
CHECK_FALSE(can_assign);
|
||||
|
||||
constexpr bool can_insert = is_insert_callable<ContainerType, Iterator1Type, Iterator2Type>::value;
|
||||
CHECK_FALSE(can_insert);
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user