I need a function template that only accepts non-integral types, if the arguments are iterators i made (i made my own class and using enable_if and a tag i manage to deduce whether or not the params are the iterators I created or not)
template <typename InputIterator>
foo (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type(),
typename ft::enable_if<InputIterator::InputIter, InputIterator>::type = NULL)
{
insert(begin(), first, last);
}
I want to make sure the parameters passed to the function are either my own iterator or a bidirectional iterator, however i thought this would be much easier if i could just check if the "InputIterator" is simply non integral but i dont know what is needed precisely to implement it, and am not sure if its a good idea since at the end of the day what i really need is to make sure its an iterator that fits my criterias.
How should i proceed ? what functions are worth looking into ?
am using -std=c 98, so am sticking to the c 98 libraries, so no c 11 or after functionality that came out after 98.
CodePudding user response:
You can create some type traits yourself to get SFINAE.
Since it's C 98, you can start by creating some traits that are included in the newer standards:
template<class T, class U>
struct is_same { static const bool value; };
template<class T, class U> const bool is_same<T,U>::value = false;
template<class T>
struct is_same<T, T> { static const bool value; };
template<class T> const bool is_same<T,T>::value = true;
template<bool B, class T = void> struct enable_if {};
template<class T> struct enable_if<true, T> { typedef T type; };
You can then build your own trait:
template<class It>
struct accepted_iterator {
static const bool value;
};
#include <iterator>
template<class It>
const bool accepted_iterator<It>::value = // add the accepted iterator categories here:
is_same<typename std::iterator_traits<It>::iterator_category,
std::bidirectional_iterator_tag>::value ||
is_same<typename std::iterator_traits<It>::iterator_category,
std::random_access_iterator_tag>::value;
And checking the iterator type, SFINAE style:
template <typename InputIterator>
typename enable_if<accepted_iterator<InputIterator>::value>::type
foo (InputIterator first, InputIterator last) {
}
CodePudding user response:
Since you are limited to C 98 it is best to try animate SFINAE tools available in later versions c 03
. This way code will be more familiar for future maintainer.
For example C 98 do not have following tools: std::enable_if
, std::iterator_traits
std::is_integral
.
Your case is quite simple, so it is not hard, but lots of boiler plate is needed:
#include <numeric>
template <typename T>
struct is_integer {
static const bool value = false;
};
template <>
struct is_integer<int> {
static const bool value = true;
};
template <>
struct is_integer<char> {
static const bool value = true;
};
template <>
struct is_integer<long int> {
static const bool value = true;
};
template <>
struct is_integer<unsigned int> {
static const bool value = true;
};
template <>
struct is_integer<unsigned char> {
static const bool value = true;
};
template <>
struct is_integer<unsigned long int> {
static const bool value = true;
};
template <bool codition, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
typedef T type;
};
template <typename T>
struct iterator_traits {
typedef typename T::value_type value_type;
};
template <typename T>
struct iterator_traits<T*> {
typedef T value_type;
};
template <typename InputIterator>
typename enable_if<
is_integer<
typename iterator_traits<InputIterator>::value_type
>::value,
typename iterator_traits<InputIterator>::value_type
>::type
foo(InputIterator first, InputIterator last) {
typedef typename iterator_traits<InputIterator>::value_type type;
return std::accumulate(first, last, type(0));
}
void test() {
int arr[3] = {1, 3, 4};
foo(arr, arr 3);
}
#ifdef TEST_FAILURE
void test_faiure() {
double arr[3] = {1, 3, 4};
foo(arr, arr 3);
}
#endif
https://godbolt.org/z/f4jvoKb5E
I didn't check what was the status of boost for C 98 (especially that you didn't specified compiler), but you should check if this is already done there