2012-02-06 44 views
2

假设我有一个名为Object的类。 Object类有一个成员函数,它想从容器中读取字符串。假设函数如下:适当的模板使用

template <class InputIterator> 
void Object::add(InputIterator first, InputIterator last) { ... } 

虽然这允许呼叫者从任意容器传递一个字符串,它不表达的事实迭代器必须是一个对字符串迭代器。

在这种情况下使用模板还是应该强制调用者使用预定义的字符串容器?

+2

不清楚你想做什么。如果你只想传递字符串,你不需要使用template.But你的“目标”是什么? – 2012-02-06 18:58:28

+2

@RamyAlZuhouri:看起来他的目标是编写函数,它将* any * string容器中的迭代器作为参数。即std :: list :: iterator,std :: vector ::迭代器,但不是std :: vector ::迭代器。 – SigTerm 2012-02-06 19:13:18

+0

可能的重复http://stackoverflow.com/questions/6273793/how-to-specialize-iterator-by-its-value-type-in​​-c – SigTerm 2012-02-06 19:15:56

回答

5

不幸的是,C++目前不允许您以简明的方式编写这些信息。

C++ 11本应该用concepts来解决这个问题,但是由于一些概念上的(heh)缺陷(which have in the meantime been solved,据我所知),它们在发布之前被删除。

但是你仍然可以使用静态断言和类型特征来提供这样的概念。下实例++ 11允许写入以下代码:

template <class InputIterator> 
void Object::add(InputIterator first, InputIterator last) { 
    static_assert(
     std::is_same< 
      typename std::remove_cv< 
       typename std::iterator_traits<InputIterator>::value_type 
      >::type, 
      std::string>::value, 
     "InputIterator must be of iterator type"); 
    … 
} 

尽管如此,这假定InputIterator是一个有效的迭代器类型。既然没有特质is_iterator,并且没有有意义的方式来实现这一点(据我所知),除非通过检查all required operations of an input iterator被服从,这使得它比理论上难得多。

+0

顺便说一下,这个答案假定OP实际上意味着'InputIterator'的值类型是一个字符串,否则这个问题就没有意义了。 – 2012-02-06 19:10:20

+0

我想你可能想要一个'std :: remove_cv <>',否则例如'std :: set :: iterator'会失败。 (另外,你错过了'typename'。) – ildjarn 2012-02-06 19:16:03

+0

'enable_if'很丑,但是与static_assert相比,它有明确的重载优点,这取决于他是否需要其他重载。至少值得一提 – 2012-02-06 19:16:29

-1

正如Konrad Rudolph所提到的,您可能会丢失模板构造,并且只会让add方法的签名具有字符串迭代器。或者保留模板构造。 add的实现可以通过调用什么来强制参数成为字符串迭代器。 一样,

add(InputIterator first, InputIterator last) { 
if (first.begin == last.end) { do something } 
} 

这将不要求第一和最后一个是字符串迭代器,但如果first.begin和/或last.end不合法的,编译器会抱怨。

+0

我想他想接受'std :: vector :: iterator' – 2012-02-06 19:17:18