Search code examples
c++stliteratorc++98

Function template accepting only non integral types (specifially bidirectional iterators)


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 any functionality that came out after 98.


Solution

  • 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
    

    live demo small improvment

    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 and if it could be used by your compiler.