函数模板只接受非整数类型(特别是双向迭代器)
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
我没有检查 C++98 的 boost 状态是什么(特别是你没有指定编译器),但你应该检查是否已经在那里完成了它是否可以被你使用编译器。
我需要一个只接受非整数类型的函数模板,如果参数是我制作的迭代器(我制作了自己的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
我没有检查 C++98 的 boost 状态是什么(特别是你没有指定编译器),但你应该检查是否已经在那里完成了它是否可以被你使用编译器。