【问题标题】:Appropriate Template Use适当的模板使用
【发布时间】:2012-02-06 18:54:35
【问题描述】:

假设我有一个名为 Object 的类。 Object 类有一个成员函数,它想从容器中读取字符串。假设函数如下所示:

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

虽然这允许调用者从任意容器传递字符串,但它并不表示迭代器必须是一对字符串迭代器。

在这种情况下使用模板是否仍然合适,还是应该强制调用者使用预先确定的字符串容器?

【问题讨论】:

  • 不清楚你想做什么。如果你只想传递字符串,你不需要使用模板。但是你的“目标”是什么?
  • @RamyAlZuhouri:看起来他的目标是编写一个函数,将 any 字符串容器中的迭代器作为参数。 IE。 std::list<:string>::iterator, std::vector<:string>::iterator,但不是 std::vector::iterator.
  • @RamyAlZuhouri SigTerm 是正确的。

标签: c++ templates coding-style iterator generic-programming


【解决方案1】:

不幸的是,C++ 目前不允许您以简洁的方式对此类信息进行编码。

C++11 本来应该用 concepts 解决这个问题,但由于一些概念(呵呵)缺陷(据我所知which have in the meantime been solved),它们在发布前就被淘汰了。

但是您仍然可以使用静态断言和类型特征来提供此类概念。例如,C++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 是否被遵守,这使得它比理论上要困难得多。

【讨论】:

  • 顺便说一句,这个答案假设 OP 实际上意味着 InputIterator 的值类型是一个字符串,否则这个问题没有意义。
  • 我想你可能想要一个std::remove_cv&lt;&gt;,否则例如std::set&lt;std::string&gt;::iterator 会失败。 (另外,您缺少typename。)
  • enable_if 很丑陋,但与 static_assert 相比具有明确的重载优点,具体取决于他是否想要其他重载。至少值得一提
【解决方案2】:

正如 Konrad Rudolph 所提到的,您可能会丢失模板构造,而只是让 add 方法的签名具有字符串迭代器。或者保留模板构造。 add 的实现可以通过调用的内容强制将参数作为字符串迭代器。 喜欢,

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

这不需要 first 和 last 是字符串迭代器,但如果 first.begin 和/或 last.end 不合法,编译器会报错。

【讨论】:

  • 我觉得他想接受std::vector&lt;std::string&gt;::iterator
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-29
  • 2017-03-20
  • 2015-08-29
  • 2020-05-17
  • 1970-01-01
  • 2021-12-29
相关资源
最近更新 更多