函数模板只接受非整数类型(特别是双向迭代器)

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

我需要一个只接受非整数类型的函数模板,如果参数是我制作的迭代器(我制作了自己的class并使用enable_if和一个标签我设法推断出是否参数是否是我创建的迭代器)

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);
        }

我想确保传递给函数的参数是我自己的迭代器或双向迭代器,但是我认为如果我可以检查“InputIterator”是否只是非整数,这会容易得多,但我不知道具体需要什么来实现它,也不确定这是否是个好主意,因为归根结底,我真正需要的是确保它是一个符合我的标准的迭代器。

我应该如何进行?哪些功能值得研究?

我正在使用 -std=c++98,所以我坚持使用 c++98 库,所以没有 c++11 或 98 之后出现的任何功能。

您可以自己创建一些类型特征来获取 SFINAE。

由于它是 C++98,您可以从创建新标准中包含的一些特征开始:

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; };

然后您可以建立自己的特质:

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;

并检查迭代器类型,SFINAE 风格:

template <typename InputIterator>
typename enable_if<accepted_iterator<InputIterator>::value>::type
foo (InputIterator first, InputIterator last) {

}

由于您仅限于 C++98,因此最好尝试在更高版本中提供的动画 SFINAE 工具 c++03。这样代码对于未来的维护者来说会更加熟悉。

例如 C++98 没有以下工具: std::enable_if, std::iterator_traits std::is_integral.

你的案例很简单,所以不难,但是需要很多样板:

#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

我没有检查 C++98 的 boost 状态是什么(特别是你没有指定编译器),但你应该检查是否已经在那里完成了它是否可以被你使用编译器。