Problem with templates

Dear all,

I am having an issue with templates.
It is strange because the very very same line of code compiles well if it is inside main, but not if it is inside a function.

The error message that I get is the following:


trycmp.cpp: In function 'void freefunct(Component<T>*)':
trycmp.cpp:30: error: missing template arguments before '>' token
trycmp.cpp:30: error: expected primary-expression before ')' token


Below I report a minimal version of the code I am working on, which reproduces the same problem. I would be grateful if anyone could help me in finding out what is going on.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<set>

template<class T>
class Maximal
{
	public:
		typedef std::set<T> EdgSet;
		typedef typename EdgSet::reverse_iterator EdgIter;
		static EdgIter edgBegin(const EdgSet& S)  {return S.rbegin();}
		
};

template<class T>
class Component
{
	public:
		std::set<T>	outEdg;
		template<template<class U> class OP> inline
		typename OP<T>::EdgIter  outBegin() const  {return OP<T>::edgBegin(this->outEdg);}

	Component() {}

		~Component() {}
};


template<class T>
void freefunct(Component<T>* conn) 
{
	conn->outBegin<Maximal>();
	return;
}


int main()
{
	Component<int>* conn = new Component<int>;
	conn->outBegin<Maximal>();
		
	freefunct<int>(conn); //This is where I get the issue. If I comment it out, as well as the definition of freefunct, it compiles properly

	return 0;
}


I thank you all in advance.
Panecasareccio.

You must use the template keyword as a "disambiguator".

27
28
29
30
31
32
template<class T>
void freefunct(Component<T>* conn) 
{
    conn->template outBegin<Maximal>();
    return;
}


http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/topic/com.ibm.xlcpp8l.doc/language/ref/keyword_template_qualifier.htm

http://en.cppreference.com/w/cpp/language/dependent_name#The_template_disambiguator_for_dependent_names
Last edited on
Hello,

I thank you for your help.

I am still unclear about one thing. From the liks you gave me I see that without the disambiguator the angle bracket that opens the template is interpreted as a less operator.'

However, why don't I get the same error when thesame call is made from main() instead of from. Freefunct()?

I thank you again,
Panecasareccio
However, why don't I get the same error when thesame call is made from main() instead of from. Freefunct()?

It happens because main() is a function and freefunct() is a template (more specifically a function template).

If freefunct() was a "regular" function instead of a function template, the compiler wouldn't get confused.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ...

void freefunct2(Component<int> *conn)
{
    conn->outBegin<Maximal>();
}

int main()
{
    Component<int>* conn = new Component<int>;
    conn->outBegin<Maximal>();

    freefunct2(conn);
    delete conn; // forgetting to deallocate memory causes a memory leak
}

Last edited on
in main, the type of conn and all its members is known. In freefunct it isn't known - the compiler may yet encounter a specialization of Component which redefines outBegin as a member variable or as a member type (or perhaps doesn't define it at all).
@ JLBorges: I saw your reply, and I don't know why you deleted it. Let me know via PM if you want me to edit it out.

JLBorges wrote:
> why don't I get the same error when thesame call is made from main()

In a template that we write, there are two kinds of names that could be used - dependant names and non-dependant names. A dependant name is a name that depends on a template parameter (what a dependant name refers to could be something different for each different instantiation of the template); a non-dependant name has the same meaning irrespective of what the template parameters are.

As a consequence, C++ templates are subject to "two-phase name lookup". When a template is initially parsed (phase one, before any template instantiation has actually taken place) the parser needs to be told if a dependant name is the name of a template.

In freefunct<T>(), Component<T>::outBegin is a dependant name. It depends on what T is
(Component<T> might have been specialized for some type).

In main(), there are no dependant names, there is no two-phase name lookup, there is no ambiguity about what Component<int>::outBegin is.

> I don't know why you deleted it.

I deleted it because after I posted it, I saw that Cubbi had already answered the question. I was essentially repeating, in slightly different words, what had been said earlier.

Keep it, if you feel that it is useful.

EDIT: Also hadn't seen your (Catfish666) post till a few seconds ago.
Last edited on
Topic archived. No new replies allowed.