1

Inside the declaration of the class Density, I built these member function:

class Density {
public:
    template <typename Container>
    void printStream (Container<Point>::iterator lo, Container<Point>::iterator hi);
......
};

In the cpp file:

template <typename Container>
void Density::printStream (Container<Point>::iterator lo, Container<Point>::iterator hi)
{
...
}

But get these errors when trying to compile:

src/../include/density.hpp:166:23: error: 'Container' is not a template
src/../include/density.hpp:166:50: error: expected unqualified-id before 'lo'
src/../include/density.hpp:166:50: error: expected ')' before 'lo'
src/../include/density.hpp:166:50: error: expected initializer before 'lo'
src/density.cpp: In member function 'void Density::startAlgorithm()':
src/density.cpp:291:43: error: 'printStream' was not declared in this scope
src/density.cpp: At global scope:
src/density.cpp:327:28: error: 'Container' is not a template
src/density.cpp:327:55: error: expected unqualified-id before 'lo'
src/density.cpp:327:55: error: expected ')' before 'lo'
src/density.cpp:327:55: error: expected initializer before 'lo'

What should I modify? And also, why, as I'd like to understand this issue.

Luis
  • 1,236
  • 5
  • 22
  • 31

1 Answers1

4

NB. As commented, you might not be aware of the implications that using templates has on the visibility of template definitions in the header files. Let me point you to the entry for that: Why can templates only be implemented in the header file?


Using a template template argument:

template <template <typename...> class Container>
void Density::printStream ()
{
    typename Container<Point>::iterator lo;
    typename Container<Point>::iterator hi;
}

What you are trying to do, seems to me to be impossible, since the iterator arguments are non-deducible context, so you'd end up explicitely specifying the container type anyways:

   density_instance.printStream<std::vector>(it1, it2);

Note, however, that's not really a problem, since you probably don't really care about the precise type of the container. The idiomatic way would be:

template <typename It>
    void printStream (It lo, It hi);  

which you can freely call using

std::vector<int> v { 1,2,3 };
density_instance.printStream(begin(v), end(v));

But also with a non-class container, since the iterators are what matters:

const int a[] = { 1,2,3 };
density_instance.printStream(std::begin(a), std::end(b));
Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633
  • 1
    Is it really standard conform to use `...` and only provide one argument (i.e. omit the allocator argument)? – celtschk Jun 09 '13 at 17:15
  • @juanchopanza Oh, good point. I'm going to "fix" that linking to the faq: **[A: Why can templates only be implemented in the header file?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file/495056#495056)** – sehe Jun 09 '13 at 17:16
  • @celtschk I certainly hope so, since I don't think many people _always_ specify the allocator type. Now, I have a hunch you're probably on to the "things are not being deduced here" thing that I also addressed in the remainder of my answer :) – sehe Jun 09 '13 at 17:17
  • I think you forgot to remove `` from your last two examples. – catscradle Jun 09 '13 at 17:21
  • The point is, in C++03, it would have seemed just as natural to use `template – celtschk Jun 09 '13 at 17:26
  • @celtschk Well, as per the standard, `std::vector` is declared as a class template with two "formal" type template arguments. So, if you wanted it to match without variadics, you'd need `template – sehe Jun 09 '13 at 17:40
  • 1
    @celtschk You're right: that `template class` as a template template parameter matches `template class vector;` as an argument is a special rule. Generally speaking I recommend avoiding template template parameters altogether as they are unflexible (e.g. even `template class` won't accept `std::array`, as it involves a non-type template parameter) and the functionality they appear to provide can be reproduced in other ways (e.g. allocators have a mechanism to 'rebind' their template arguments, should they be class templates in the first place). – Luc Danton Jun 09 '13 at 17:42
  • @not-sehe: Thank you! I'll use the second option with ``. I don't know why you said it's overkill, but I understand it and find it simpler. And it's working. – Luis Jun 09 '13 at 18:24
  • @Luis I meant to say that what you were doing seemed like overkill, because it can be done much simpler :) I'll edit it to make it clearer. – sehe Jun 09 '13 at 18:28