why doesn't this compile?

B

Bas

Hello everybody,
I've tried this small program, but ik get the compiler error:

Error 1 error C2768: 'functie' : illegal use of explicit template arguments
d:\projects\templatespectest\templatespectest\templatespectest.cpp 17


on the second template specialisation. I do not understand why.
The rest of the templates are OK.

thanks, Bas From Holland

#include <iostream>

template<class T> int functie(T val)
{
T temp = val;
return 0;
}

template<class T> int functie<T*>(T* val)
{
T* temp = val;
return 0;
}

template<> int functie<void*>(void* val)
{
void* temp = val;
return 0;
}

template<> int functie<int *>(int* val)
{
int* temp = val;
return 0;
}



int _tmain(int argc, _TCHAR* argv[])
{
int p = 0;
void* pV = 0;
functie<int>(p);
functie<int*>(&p);
functie<void*>(pV);

std::cin.get();
return 0;
}
 
F

Francesco S. Carta

Hello everybody,
I've tried this small program, but ik get the compiler error:

Error 1 error C2768: 'functie' : illegal use of explicit template arguments
d:\projects\templatespectest\templatespectest\templatespectest.cpp 17

on the second template specialisation. I do not understand why.
The rest of the templates are OK.

thanks, Bas From Holland

#include <iostream>

template<class T> int functie(T val)
{
 T temp = val;
 return 0;

}

template<class T> int functie<T*>(T* val)
{
 T* temp = val;
 return 0;

}

template<> int functie<void*>(void* val)
{
 void* temp = val;
 return 0;

}

template<> int functie<int *>(int* val)
{
 int* temp = val;
 return 0;

}

int _tmain(int argc, _TCHAR* argv[])
{
 int p = 0;
 void* pV = 0;
 functie<int>(p);
 functie<int*>(&p);
 functie<void*>(pV);

 std::cin.get();
 return 0;

}

gcc 3.4.5 chokes on this - which is not line 17 of your posted code,
but line 10:
template<class T> int functie<T*>(T* val)

Solved changing it to:

template<class T> int functie(T* val)

That is: not specialization but overloading.

All the rest works fine for me - apart for your weird main
declaration.

Don't cut any header inclusion the next time, post the code exactly as
you have fed it to the compiler (refer to the FAQ about how to post).

Have good time,
Francesco
 
B

Balog Pal

Bas said:
Hello everybody,
I've tried this small program, but ik get the compiler error:

Error 1 error C2768: 'functie' : illegal use of explicit template
arguments
d:\projects\templatespectest\templatespectest\templatespectest.cpp 17

on the second template specialisation. I do not understand why.
The rest of the templates are OK.
template<class T> int functie(T val);
template<class T> int functie<T*>(T* val);

This would be a partial specialisation of a function template, that is not
allowed. You can only partially specialize class templates.
template<> int functie<void*>(void* val);

Total specialization is okay.

Use overload like Francesco showed.
 
B

Bas

Ahaaaa. I didn't know that.
What a pity that it is not possible, but the alternative is of course OK.
Thanks a lot.

Bas from Holland.
 
B

Bas

...but I'm afraid it does not work.
I have changed the code somewhat so it is more clear what happens and what I
mean.

When I debug, I see that in case of the statement
functie<int*>(&p);

is executed the function

template<class T> int functie(T val)
{
T temp = val;
return 0;
}
is called in stead of

template<class T> int functie(T* val)
{
T* temp;
*temp = *val;
return 0;
}

resulting in that the pointers are set equal in stead of the int values.
That is why I tried the specialisation first.


Code is:

#include <iostream>

template<class T> int functie(T val)
{
T temp = val;
return 0;
}

template<class T> int functie(T* val)
{
T* temp;
*temp = *val;
return 0;
}

template<> int functie<void*>(void* val)
{
void* temp = val;
return 0;
}


int main(int argc, char* argv[])
{
int p = 0;

functie<int>(p);
functie<int*>(&p);

std::cin.get();
return 0;
}
 
F

Francesco S. Carta

..but I'm afraid it does not work.
I have changed the code somewhat so it is more clear what happens and what I
mean.

When I debug, I see that in case of the statement
 functie<int*>(&p);

 is executed the function

template<class T> int functie(T val)
{
 T temp = val;
 return 0;}

 is called in stead of

template<class T> int functie(T* val)
{
 T* temp;
 *temp = *val;
 return 0;

}


You must call either of these:

-------
functie(&p);
functie<int>(&p);
-------

In order to ensure that "template<class T> int functie(T* val)" gets
called. Template call resolution can become tricky, check out the code
I'll post here at the bottom of this post.

But before:
T* temp;
*temp = *val;

No, never do things like that.
You have declared one pointer, you have _not_ set it to any valid
address, _but_ you are dereferencing it anyway. The above is a call
for hell to come, watch out.

Try this one and do your tests.

-------
#include <iostream>

using namespace std;

template<class T> void functie(T val) {
cout << " Called:" << endl;
cout << " template<class T> int functie(T val)" << endl << endl;
}

template<class T> void functie(T* val) {
cout << " Called:" << endl;
cout << " template<class T> int functie(T* val)" << endl << endl;
}

template<> void functie<void*>(void* val) {
cout << " Called:" << endl;
cout << " template<> void functie<void*>(void* val)" << endl <<
endl;
}

int main() {
int p = 0;
void* pV = &p;

cout << "exec: functie(p);" << endl;
functie(p);

cout << "exec: functie(&p);" << endl;
functie(&p);

cout << "exec: functie<int>(&p);" << endl;
functie<int>(&p);

cout << "exec: functie<int*>(&p);" << endl;
functie<int*>(&p);

cout << "exec: functie(pV);" << endl;
functie(pV);

cout << "exec: functie<void*>(pV);" << endl;
functie<void*>(pV);

}
-------

gcc 3.4.5 outputs this:

-------
exec: functie(p);
Called:
template<class T> int functie(T val)

exec: functie(&p);
Called:
template<class T> int functie(T* val)

exec: functie<int>(&p);
Called:
template<class T> int functie(T* val)

exec: functie<int*>(&p);
Called:
template<class T> int functie(T val)

exec: functie(pV);
Called:
template<class T> int functie(T* val)

exec: functie<void*>(pV);
Called:
template<> void functie<void*>(void* val)
 
G

Gert-Jan de Vos

..but I'm afraid it does not work.
I have changed the code somewhat so it is more clear what happens and what I
mean.

When I debug, I see that in case of the statement
 functie<int*>(&p);

 is executed the function

template<class T> int functie(T val)
{
 T temp = val;
 return 0;}

 is called in stead of

template<class T> int functie(T* val)
{
 T* temp;
 *temp = *val;
 return 0;

}

resulting in that the pointers are set equal in stead of the int values.
That is why I tried the specialisation first.

Code is:

#include <iostream>

template<class T> int functie(T val)
{
 T temp = val;
 return 0;

}

template<class T> int functie(T* val)
{
 T* temp;
 *temp = *val;
 return 0;

}

template<> int functie<void*>(void* val)
{
 void* temp = val;
 return 0;

}

int main(int argc, char* argv[])
{
 int p = 0;

 functie<int>(p);

This one calls functie said:
 functie<int*>(&p);

This one calls functie<T>(T) with T = int*.

You specify the template argument int* explicitly,
this means that these overloads are considered:

int functie<int*>(int*);
int functie<int*>(int**);

Note that the second overload takes a T* parameter.

Your call matches the first overload.

Normally you don't specify the template arguments for
function templates explicitly, rather you let the compiler
find the best matching overload automatically. In that case:

functie(&p)

will find the second overload as a better (more specific) match.
 
F

Francesco S. Carta

template<class T> void functie(T val) {
^^^^
  cout << " template<class T> int functie(T val)" << endl << endl;
^^^

Sorry, messed up the return values into the messages.

Gert's comment is very important: dig the issue and work out what T
gets "translated to" in the different cases.
 
B

Bas

Thanks guys,
tomorrow I will dig further into it.

Bas

..but I'm afraid it does not work.
I have changed the code somewhat so it is more clear what happens and what
I
mean.

When I debug, I see that in case of the statement
functie<int*>(&p);

is executed the function

template<class T> int functie(T val)
{
T temp = val;
return 0;}

is called in stead of

template<class T> int functie(T* val)
{
T* temp;
*temp = *val;
return 0;

}

resulting in that the pointers are set equal in stead of the int values.
That is why I tried the specialisation first.

Code is:

#include <iostream>

template<class T> int functie(T val)
{
T temp = val;
return 0;

}

template<class T> int functie(T* val)
{
T* temp;
*temp = *val;
return 0;

}

template<> int functie<void*>(void* val)
{
void* temp = val;
return 0;

}

int main(int argc, char* argv[])
{
int p = 0;

functie<int>(p);

This one calls functie said:
functie<int*>(&p);

This one calls functie<T>(T) with T = int*.

You specify the template argument int* explicitly,
this means that these overloads are considered:

int functie<int*>(int*);
int functie<int*>(int**);

Note that the second overload takes a T* parameter.

Your call matches the first overload.

Normally you don't specify the template arguments for
function templates explicitly, rather you let the compiler
find the best matching overload automatically. In that case:

functie(&p)

will find the second overload as a better (more specific) match.
 
A

Andrey Tarasevich

Bas said:
Hello everybody,
I've tried this small program, but ik get the compiler error:

Error 1 error C2768: 'functie' : illegal use of explicit template arguments
d:\projects\templatespectest\templatespectest\templatespectest.cpp 17


on the second template specialisation. I do not understand why.
The rest of the templates are OK.

You are trying to use partial specialization with function templates.
C++ language has no such feature. Partial specialization is only
possible with class templates.

As for function templates you have to make do with explicit
specialization and/or plain overloading.

As a workaround, you can always wrap your function into a template class
and use partial specialization with the class. But that is not always
acceptable. Depends on how you use your function.
 
B

Bas

Andrey Tarasevich said:
You are trying to use partial specialization with function templates. C++
language has no such feature. Partial specialization is only possible with
class templates.

As for function templates you have to make do with explicit specialization
and/or plain overloading.

As a workaround, you can always wrap your function into a template class
and use partial specialization with the class. But that is not always
acceptable. Depends on how you use your function.

You are completely right. I had not done for quite a while anything with
C++.
After the answers of the other people I've read Bjarne Stroustrup's book
again (well.. the part on templates).
I've found the solution by now!

Bas
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Staff online

Members online

Forum statistics

Threads
473,961
Messages
2,570,130
Members
46,689
Latest member
liammiller

Latest Threads

Top