Template class problem

  • (2 Pages)
  • +
  • 1
  • 2

18 Replies - 821 Views - Last Post: 03 July 2013 - 07:16 PM Rate Topic: -----

#16 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1072
  • View blog
  • Posts: 4,532
  • Joined: 09-June 09

Re: Template class problem

Posted 03 July 2013 - 12:31 AM

Quote

So basically, when you use a typename as an argument to a template you must use a prefix of 'typename'.
Okay, I will definitely look into it; this was incredibly helpful.
Thanks for the help


No, only when you use a dependent name template parameter
i.e.
template<typename T>
void print_data(T data) {
   T::iterator iter; /* what did the programmer mean by this?



The programmer assumed that the template type specifies a type like so
class Data {
   class iterator {
      int *iter;
   /* etc */
  }
};



However, the compiler assumes you mean't this
class Data {
   static int *iterator;
};



These two of the same type, define their iterators differently and the compiler parses these differently when passed to the print_data function. To tell the compiler you are using the upper case, you must specify the typename prefix.

This really all has to do with how templates are implemented and the information they need to know before hand before generating the code during pre processing, the programmer doesn't necessary need to understand why. Just know that if you receive the error, you should realize you are using a dependent name and prefix the declaration with typename.

This post has been edited by jjl: 03 July 2013 - 12:33 AM

Was This Post Helpful? 2
  • +
  • -

#17 salazar  Icon User is offline

  • D.I.C Addict

Reputation: 87
  • View blog
  • Posts: 539
  • Joined: 26-June 13

Re: Template class problem

Posted 03 July 2013 - 12:57 AM

Okay, i'm still a little confused. Could you explain why the second one contains 'static'? So T is dependent, and when I use it as a argument to another template I must use a prefix of 'typename' in order to let the compiler know what I really mean? Thanks for the help.

This post has been edited by salazar: 03 July 2013 - 01:00 AM

Was This Post Helpful? 0
  • +
  • -

#18 Skydiver  Icon User is online

  • Code herder
  • member icon

Reputation: 3540
  • View blog
  • Posts: 10,959
  • Joined: 05-May 12

Re: Template class problem

Posted 03 July 2013 - 05:48 AM

View Postsalazar, on 03 July 2013 - 02:20 AM, said:

It sill compiles fine using g++. Maybe its the compiler.


Using this code in Code::Blocks and GCC v4.7.0:
#include <iostream>
#include <set>
#include <string>

using namespace std;

template <class T>        // <- use 'class' instead of 'typename'
void print_set(set<T> s)
{
	/* typename */ set<T>::iterator iter;
	for(iter = s.begin(); iter != s.end(); ++iter)
	{
		cout << *iter << " ";
	}
	cout << endl;
}

int main()
{
    set<int> evens;

    for(int i = 0; i < 10; i++)
        evens.insert(2*(i + 1));

    print_set(evens);

    set<string> names;
    names.insert("Picard");
    names.insert("Riker");
    names.insert("Troi");
    names.insert("Crusher");
    names.insert("Worf");

    print_set(names);

    return 0;
}



I get the following errors:
C:\z\Test\CBCpp\main.cpp: In function 'void print_set(std::set<T>)':
C:\z\Test\CBCpp\main.cpp:10:17: error: need 'typename' before 'std::set<T>::iterator' because 'std::set<T>' is a dependent scope
C:\z\Test\CBCpp\main.cpp:10:34: error: expected ';' before 'iter'
C:\z\Test\CBCpp\main.cpp:11:6: error: 'iter' was not declared in this scope
C:\z\Test\CBCpp\main.cpp: In instantiation of 'void print_set(std::set<T>) [with T = int]':
C:\z\Test\CBCpp\main.cpp:25:20:   required from here
C:\z\Test\CBCpp\main.cpp:10:17: error: dependent-name 'std::set<T>::iterator' is parsed as a non-type, but instantiation yields a type
C:\z\Test\CBCpp\main.cpp:10:17: note: say 'typename std::set<T>::iterator' if a type is meant
C:\z\Test\CBCpp\main.cpp: In instantiation of 'void print_set(std::set<T>) [with T = std::basic_string<char>]':
C:\z\Test\CBCpp\main.cpp:34:20:   required from here
C:\z\Test\CBCpp\main.cpp:10:17: error: dependent-name 'std::set<T>::iterator' is parsed as a non-type, but instantiation yields a type
C:\z\Test\CBCpp\main.cpp:10:17: note: say 'typename std::set<T>::iterator' if a type is meant



(Which reminds me, I need to update my compiler...)

View Postsalazar, on 03 July 2013 - 03:57 AM, said:

Okay, i'm still a little confused. Could you explain why the second one contains 'static'? So T is dependent, and when I use it as a argument to another template I must use a prefix of 'typename' in order to let the compiler know what I really mean? Thanks for the help.


You can read more about static here: http://en.cppreferen...language/static

The reason why the second one contains static there was so that he could setup a straw man for his example of why you needed typename. Without static, the compiler would have known that he needed to instantiate a class to access the variable and therefore given a different error message. By using a static variable, the compiler knows that he can access the static variable without creating an instance.
Was This Post Helpful? 2
  • +
  • -

#19 salazar  Icon User is offline

  • D.I.C Addict

Reputation: 87
  • View blog
  • Posts: 539
  • Joined: 26-June 13

Re: Template class problem

Posted 03 July 2013 - 07:16 PM

I got nearly identical errors using g++. But after using dealing with the dependency issues of template arguments with the typename prefix, I was able get it successfully compiled.

Thanks a lot for elucidating the reason for the static for me. It didn't realize that there was such a difference on whether or not you declare with static. I'll definitely read up on this.
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2