2

Suppose I have a class called Object. The Object class has a member function that wants to read in strings from a container. Suppose the function looks like this:

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

While this allows the caller to pass strings from an arbitrary container, it does not express the fact that the iterators must be a pair of string iterators.

Is it still appropriate to use templates in this case, or should I force the caller to use a predetermined container of strings?

Sam Hertz
  • 161
  • 9
  • 2
    Is not clear what you want to do.If you want to pass only strings you don't need to use template.But what's your "goal" ? – Ramy Al Zuhouri Feb 06 '12 at 18:58
  • 2
    @RamyAlZuhouri: It looks like his goal is to write function that takes iterator from *any* string container as an argument. I.e. std::list::iterator, std::vector::iterator, but not std::vector::iterator. – SigTerm Feb 06 '12 at 19:13
  • Possible duplicate of http://stackoverflow.com/questions/6273793/how-to-specialize-iterator-by-its-value-type-in-c – SigTerm Feb 06 '12 at 19:15
  • @RamyAlZuhouri SigTerm is correct. – Sam Hertz Feb 06 '12 at 19:38

2 Answers2

5

Unfortunately, C++ doesn’t at the moment allow you to codify such information in a concise way.

C++11 was supposed to solve this with concepts but they were chucked out before the release due to some conceptual (heh) deficiencies (which have in the meantime been solved, as far as I know).

But you can still provide such concepts using static assertion and type traits. C++11 for instance allows to write the following code:

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

Still, this assumes that InputIterator is a valid iterator type. Since there is no trait is_iterator and no meaningful way to implement this (as far as I know) except by checking that all required operations of an input iterator are obeyed, this makes it far more difficult than it could theoretically be.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
  • By the way, this answer assumes that the OP actually meant that the value type of `InputIterator` is a string because otherwise the question makes no sense. – Konrad Rudolph Feb 06 '12 at 19:10
  • I think you may want a `std::remove_cv<>`, otherwise e.g. `std::set::iterator` would fail. (Also, you're missing a `typename`.) – ildjarn Feb 06 '12 at 19:16
  • `enable_if` is ugly, but has definite overloading pros compared to a static_assert, depending on if he wants other overloads. It's at least worth mentioning – Mooing Duck Feb 06 '12 at 19:16
-1

As Konrad Rudolph mentioned, you could lose the template construct and just have the add method's signature have string iterators. Or keep the template construct. The implementation of add may enforce the arguments to be string iterators by what gets called. Like,

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

This won't require that first and last are string iterators but the compiler will complain if first.begin and/or last.end aren't legit.

Todd Murray
  • 423
  • 2
  • 7