C++ 在C+中,如何根据迭代器的值类型专门化迭代器+;?

C++ 在C+中,如何根据迭代器的值类型专门化迭代器+;?,c++,templates,iterator,template-specialization,C++,Templates,Iterator,Template Specialization,是否可以根据迭代器模板参数的值\u类型专门化迭代器模板参数 我有一个具有以下原型的函数 template<typename InputIterator> void f(InputIterator first, InputIterator last); 模板 无效f(输入者第一,输入者最后); 如果inputierator::value\u type是SomeSpecificType,我想特别处理。您可以使用一些中间结构来获得所需的部分模板专门化。像这样的东西应该能奏效 templ

是否可以根据迭代器模板参数的
值\u类型专门化迭代器模板参数

我有一个具有以下原型的函数

template<typename InputIterator>
void f(InputIterator first, InputIterator last);
模板
无效f(输入者第一,输入者最后);

如果
inputierator::value\u type
SomeSpecificType,我想特别处理。

您可以使用一些中间结构来获得所需的部分模板专门化。像这样的东西应该能奏效

template<typename T, typename V>
struct f_impl
{
  static void f( T first, T last ) {...}; //Default version
};

template<typename T>
struct f_impl<T, SomeSpecificType>
{
   static void f(T first,T last) {...}; //Specialisation
};

template<typename InputIterator> void f(InputIterator first, InputIterator last)
{
  f_impl<
      InputIterator,
      typename std::iterator_traits<InputIterator>::value_type
  >::f(first,last);
};
模板
结构f_impl
{
静态void f(T first,T last){…};//默认版本
};
模板
结构f_impl
{
静态空位f(T first,T last){…};//专门化
};
模板无效f(先输入迭代器,后输入迭代器)
{
f_impl<
输入者,
typename std::迭代器特征::值类型
>::f(第一个,最后一个);
};
那么:

template<typename T>
typename std::enable_if<std::is_same<typename T::value_type, SomeType>::value, void>::type
f(T first, T second);
模板
typename std::enable_if::type
f(T第一,T第二);

使用SFINAE,假设[\u c]
是相同的
或者来自Boost或者
(并且分别符合
Boost:
或者
std:
的条件):

模板
typename启用\u如果<
!你也一样吗<
typename std::迭代器特性::值类型,
某种特定类型
>::价值
>::类型
f(先输入后输入)
{
//默认实现。
}
模板
typename启用\u如果<
你也一样吗<
typename std::迭代器特性::值类型,
某种特定类型
>::价值
>::类型
f(先输入后输入)
{
//特例
}

在Boost情况下,使用类似于上述内容的
Boost::enable_if_c
。您可以使用
boost::enable_if
并去掉
::值
,但还必须使用例如
boost::disable_if
,这将起作用。这种类型的专门化只适用于结构,所以我不能用函数来实现

template <typename InputIterator, typename ValueType = typename InputIterator::value_type>
struct foobar
{
    static void invoke(InputIterator first, InputIterator second)
    {
        // ...
    }
};

template <typename InputIterator>
struct foobar<InputIterator, SomeSpecificType>
{
    static void invoke(InputIterator first, InputIterator second)
    {
        // ...
    }
};
模板
结构foobar
{
静态void调用(第一个InputIterator,第二个InputIterator)
{
// ...
}
};
模板
结构foobar
{
静态void调用(第一个InputIterator,第二个InputIterator)
{
// ...
}
};

这不需要您设置类型。它应该是自动推断出来的。

叫我天真,但为什么下面的内容不够呢

struct MyType; // the only type I want

#include <iterator>
typedef std::iterator<std::input_iterator_tag, MyType> MyIt;

void f(const MyIt & begin, const MyIt & end)
{
   /* ... */
}
struct MyType;//我要的唯一类型
#包括
typedef std::迭代器MyIt;
无效f(常量MyIt&开始、常量MyIt&结束)
{
/* ... */
}

好吧,忘了上面的,那是胡说八道。对于C++0x,这里有一种方法,这正是Luc在上面给出的正确答案:

#include <vector>
#include <iterator>
#include <type_traits>

// "int" is our desired iterator value type, "void" is f's return type.
template <typename It>
typename std::enable_if<std::is_same<int, typename std::iterator_traits<It>::value_type>::value, void>::type
f(const It & begin, const It & end) { /* your function here */ }

int main()
{
  std::vector<double> x;
  std::vector<int> y;

  //f(x.cbegin(), x.cend()); // error
  f(y.cbegin(), y.cend());   // works
}
#包括
#包括
#包括
//“int”是我们想要的迭代器值类型,“void”是f的返回类型。
模板
typename std::enable_if::type
f(const It&begin,const It&end){/*此处的函数*/}
int main()
{
std::向量x;
std::向量y;
//f(x.cbegin(),x.cend());//错误
f(y.cbegin(),y.cend());//有效
}

我不确定你想要什么。这是用于模板专用化的吗?有什么原因不能在正文中使用上面提到的InputIterator::value\u类型吗?嗯,你可以做各种类型的类型跟踪工作,但是如果你已经想要一个具有特定值类型的输入迭代器,这难道不意味着你得到的是一个基类
std::iterator
的派生类吗?所以你根本不需要任何模板,只需要一个固定的函数。@Kerrek:不,这并不意味着。迭代器不共享公共基类。举个例子:指针是迭代器。@Kerrek:
std::iterator
不是多态的,不实现任何有用的操作。你说得对,很抱歉。关于迭代器,我们还学到了一件事:-)Luc下面的回答很好地解决了这个问题。@Martinho Fernandes:您也可以约束
f
的第二个版本来删除ambiguity@Martino:只要正确地
enable\u(如果
每个重载都正确的话),您就可以拥有所需的任意多个重载。@Dani:我看不到添加该约束的简单方法,没有像@Michael Anderson's answer中那样的包装器函数调用。@Martinho:我在AXE中有很多运算符重载,都是通过SFINAE设施完成的。当您需要保持完美的转发时,您将无法进行任何不同的操作。请注意,
boost::enable_(如果
需要一个元函数),而
std::enable_(如果
需要一个
bool
值)。本文中正确的Boost推论是
Boost::enable_if_c
.D'oh;这就是我通过阅读代码和只浏览周围文本得到的结果:-P
typename std::iterator\u traits::value\u type
会比
typename InputIterator::value\u type
更好。现在尝试在这个专门的
f
中使用
begin
end
做任何有用的事情。好的,我明白了。从std::iterator继承仅用于类型跟踪目的。。。那没关系。真正的答案可能还需要一些打字工作。
#include <vector>
#include <iterator>
#include <type_traits>

// "int" is our desired iterator value type, "void" is f's return type.
template <typename It>
typename std::enable_if<std::is_same<int, typename std::iterator_traits<It>::value_type>::value, void>::type
f(const It & begin, const It & end) { /* your function here */ }

int main()
{
  std::vector<double> x;
  std::vector<int> y;

  //f(x.cbegin(), x.cend()); // error
  f(y.cbegin(), y.cend());   // works
}