Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Why won't this compile...

49 views
Skip to first unread message

Doug Mika

unread,
Jun 8, 2015, 5:22:03 PM6/8/15
to
So the first problem with the following code is that it won't compile.

#include <iostream>
#include <string>
#include <vector>

using namespace std;

template <typename C>
vector<typename C> create_container(int size){
return vector<typename C> myVector(size);
}

int main()
{
cout << "Hello World" << endl;
cout<<"The size is: "<<(create_container<string>(3)).size()<<endl;

return 0;
}

Mr Flibble

unread,
Jun 8, 2015, 5:44:56 PM6/8/15
to
On 08/06/2015 22:21, Doug Mika wrote:
> #include <iostream>
> #include <string>
> #include <vector>
>
> using namespace std;
>
> template <typename C>
> vector<typename C> create_container(int size){
> return vector<typename C> myVector(size);
> }
>
> int main()
> {
> cout << "Hello World" << endl;
> cout<<"The size is: "<<(create_container<string>(3)).size()<<endl;
>
> return 0;
> }

template <typename C>
vector<C> create_container(int size){
return vector<C>(size);
}

/Flibble

Victor Bazarov

unread,
Jun 9, 2015, 9:25:58 AM6/9/15
to
On 6/8/2015 5:21 PM, Doug Mika wrote:
> So the first problem with the following code is that it won't compile.
>
> #include <iostream>
> #include <string>
> #include <vector>
>
> using namespace std;
>
> template <typename C>
> vector<typename C> create_container(int size){
> return vector<typename C> myVector(size);

I do not believe this is correct syntax, but I am not your compiler.

> }
>
> int main()
> {
> cout << "Hello World" << endl;
> cout<<"The size is: "<<(create_container<string>(3)).size()<<endl;
>
> return 0;
> }
>

...and the error message is ...?

See FAQ 5.8.

V
--
I do not respond to top-posted replies, please don't ask

Doug Mika

unread,
Jun 9, 2015, 1:34:08 PM6/9/15
to
That worked, much thanks, and it makes sense. But it leaves me wondering why then the following code has "typename C" and not merely "C" in the find_all function definition and inside of it? (code is taken from Stroustrup's book)

template<typename C, typename V>
vector<typename C::iterator> find_all(C& c, V v) //find all occurrences of v in c
{
vector<typename C::iterator> res;
for (auto p = c.begin(); p!=c.end(); ++p)
if (∗p==v) res.push_back(p);
return res;
}

red floyd

unread,
Jun 9, 2015, 1:51:50 PM6/9/15
to
Because the compiler has no way of knowing that C::iterator is a type,
so you need to tell it that.

Victor Bazarov

unread,
Jun 9, 2015, 1:52:29 PM6/9/15
to
On 6/9/2015 1:33 PM, Doug Mika wrote:
> [..] it leaves me wondering why then the following code has
> "typename
C" and not merely "C" in the find_all function definition and inside of
it? (code is taken from Stroustrup's book)

It's not "typename C". It's "typename C::iterator". It's a hint to the
compiler that the 'iterator' member of 'C' *is a typename*.

>
> template<typename C, typename V>
> vector<typename C::iterator> find_all(C& c, V v) //find all occurrences of v in c
> {
> vector<typename C::iterator> res;
> for (auto p = c.begin(); p!=c.end(); ++p)
> if (∗p==v) res.push_back(p);
> return res;
> }
>

Doug Mika

unread,
Jun 9, 2015, 1:55:21 PM6/9/15
to
The following for example will not work: (but why do we need typename C here and just C previously?)

//this won't compile, "typename" is needed, but why is it needed here but
//not previously?
template<typename C, typename V>
vector<C::iterator> find_all(C& c, V v)
{
vector<C::iterator> res;
for(auto p = c.begin(); p!=c.end(); ++p)
if(*p==v) res.push_back(p);
return res;
}

Doug Mika

unread,
Jun 9, 2015, 1:58:45 PM6/9/15
to
So what would be the rule, when do I need typename C and when do I just write C? It should be obvious that inside the <> brackets is always a type, what else could it be?

Victor Bazarov

unread,
Jun 9, 2015, 2:02:23 PM6/9/15
to
On 6/9/2015 1:55 PM, Doug Mika wrote:
>[..]
> The following for example will not work: (but why do we need typename C here and just C previously?)
>
> //this won't compile, "typename" is needed, but why is it needed here but
> //not previously?
> template<typename C, typename V>
> vector<C::iterator> find_all(C& c, V v)
> {
> vector<C::iterator> res;
> for(auto p = c.begin(); p!=c.end(); ++p)
> if(*p==v) res.push_back(p);
> return res;
> }
>

A bit impatient, aren't you?

It's good that you tried this. It's bad that you don't actually reach
for a decent book and study instead of just posting here. Find a copy
of "C++ Templates" by Vandevoorde and Josuttis, and perhaps you will get
more questions answered than raised by your attempts.

C::iterator is what's known as a "dependent name". In order for the
compiler to be able to do the syntactic analysis of the template, it has
to know what 'C::iterator' is. We need to tell it that it's a typename,
and not, say, a non-static member function. Otherwise the compiler will
need to instantiate your template before it can do the syntactic
analysis, which is not good, and probably leads to chicken-and-egg type
of problems.

Victor Bazarov

unread,
Jun 9, 2015, 2:06:06 PM6/9/15
to
Get a damn book and study. You can't expect a single rule to apply to
all freaking cases in the entire language now, can you?

> It should be obvious that inside the <> brackets is
> always a type, what else could it be?

It's *not* always a type. It can be an object. It can be a constant.
It can be a template. It can be a function pointer.

Let me spell this out for you: G-E-T A B-O-O-K A-N-D S-T-U-D-Y!

Paavo Helde

unread,
Jun 9, 2015, 3:57:20 PM6/9/15
to
Doug Mika <doug...@gmail.com> wrote in
news:4b3ec219-0acb-40c7...@googlegroups.com:

>> > template<typename C, typename V>
>> > vector<typename C::iterator>
>
> So what would be the rule, when do I need typename C and when do I
> just write C? It should be obvious that inside the <> brackets is
> always a type, what else could it be?

The last typename above applies to 'iterator', not to 'C'. The compiler
knows C is a type, but it does not have such knowledge about 'C::iterator'.

hth



Doug Mika

unread,
Jun 9, 2015, 4:05:57 PM6/9/15
to
Yes, I sort of figured that, it is nice however that someone confirms it.
(It's not explicitly written in my book)
Thanks

Marcel Mueller

unread,
Jun 9, 2015, 4:51:16 PM6/9/15
to
On 09.06.15 19.55, Doug Mika wrote:
> The following for example will not work: (but why do we need typename C here and just C previously?)
>
> //this won't compile, "typename" is needed, but why is it needed here but
> //not previously?

template<typename C> vector<C> create_container(int size) ...

Here C is replaced by the individual type at instantiation of the
template. C is always a type name because this is restricted in the
template pattern, maybe C evaluates to 'typename myclass'.

template<typename C, typename V>
vector<typename C::iterator> find_all(C& c, V v)

This is a different story. The 'typename' applies to the nested iterator
type rather than to C itself. And 'iterator' could be anything within
the type C.


Marcel
0 new messages