Solved

Template Function Specialization

Posted on 2001-09-04
15
378 Views
Last Modified: 2008-03-06
In my main program I am trying to specialize a template function for int as well as char*. However, when I compile I get 2 errors. I'm not sure what I'm doing wrong. Here is my code:

template<class T>
T randomItem(int len)
{
     return (T)0;
};

//specialization for int
//this function returns a random number of length len
template<>
int randomItem(int len)
{
     
     RandomAtom<int> atom(clock());  //a class i wrote for generating random digits or lowercase letters
     int thisDigit = 0;
     int retVal = 0;
     // first digit cannot be zero
     while (thisDigit == 0) thisDigit = atom.randomIntChar();
     while (len--)
     {
          retVal *= 10;
          retVal += thisDigit;
          thisDigit = atom.randomIntChar();
     }
     return retVal;
}

//specialization for char*
//this function returns a random string of length len
template<>
char* randomItem(int len)
{
     return(randomString(len));  
}

When I compile I get two errors:
1.error C2556: 'char *__cdecl randomItem(int)' : overloaded function differs only by return type from 'int __cdecl randomItem(int)'
see declaration of 'randomItem'

2.error C2040: 'randomItem' : 'char *(int)' differs in levels of indirection from 'int (int)'

Then if I switch the order of the two functions ( put the char* specialization before the int specialization ) I get the same errors only the other way around.  Are you only allowed to write 1 specialization?  I am using Microsoft Visual C++ 6.0 with service pack 5.  
0
Comment
Question by:industrycity
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 8
  • 6
15 Comments
 
LVL 30

Expert Comment

by:Axter
ID: 6453883
You can not do specialization for return type only.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6453886
Just like you can not overload a function by just changing the return type, you also can't specialize if all you do is change the return type.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6453895
The reason C++ does not allow you to do this is because it would create ambiquity.

Example:

int foo(int data)
{
return 0;
}

char* foo(int data)
{
return NULL;
}

int main(.....)
{
 foo(123);
}

In the above example, how would the compiler know which function main() is trying to call.
It can't, and that's why overloading a function by just changing the return type is not allowed.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 30

Expert Comment

by:Axter
ID: 6453911
You can overload the return type, if you also change the arguments.

Example:
int foo(int data)
{
return 0;
}
char* foo(char* data)
{
return NULL;
}

int main(.....)
{
foo(123);
}

Now the above overloader is not ambiquous, because the compiler knows which function you're trying to call.  It knows this because only one of the functions accepts an integer.
If you want to overload the return type in your code, you'll have to change one or more arguments.
0
 

Author Comment

by:industrycity
ID: 6454028
Do you have any suggestions as to what I should do?  Or is the situation impossible?  In other words, do I have to create two separate functions, one for creating the random integers and another for creating the random strings?
0
 

Author Comment

by:industrycity
ID: 6454044
Do you have any suggestions as to what I should do?  Or is the situation impossible?  In other words, do I have to create two separate functions, one for creating the random integers and another for creating the random strings?
0
 

Author Comment

by:industrycity
ID: 6454060
Do you have any suggestions as to what I should do?  Or is the situation impossible?  In other words, do I have to create two separate functions, one for creating the random integers and another for creating the random strings?
0
 

Author Comment

by:industrycity
ID: 6454062
Do you have any suggestions as to what I should do?  Or is the situation impossible?  In other words, do I have to create two separate functions, one for creating the random integers and another for creating the random strings?
0
 

Author Comment

by:industrycity
ID: 6454082
Do you have any suggestions as to what I should do?  Or is the situation impossible?  In other words, do I have to create two separate functions, one for creating the random integers and another for creating the random strings?
0
 
LVL 2

Expert Comment

by:udil
ID: 6454137
You can pass an out parameter to the function, instead of
using a return value.
It's probably not that pretty to use an out parameter,
but it can probably do the work.

template<class T>
void randomItem(int len, T &retVal)
{
    retVal = (T)0;
};


   udil
0
 
LVL 30

Accepted Solution

by:
Axter earned 100 total points
ID: 6454179
You could try using a dummy variable as the second argument.


Example:
template<class T>
T randomItem(int len, T dummy)
{
    return (T)0;
};

//specialization for int
//this function returns a random number of length len
template<>
int randomItem<int>(int len, int dummy)
{
    return 0;
}

//specialization for char*
//this function returns a random string of length len
template<>
char* randomItem<char*>(int len, char* dummy)
{
    return NULL;  
}

int main(int argc, char* argv[])
{
     int x = randomItem<int>(3,NULL);
     char* xc = randomItem<char*>(5,NULL);
     return 0;
}
0
 

Author Comment

by:industrycity
ID: 6454256
You solved a real vexing problem that was driving me crazy.  Thanks a lot.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6454293
Here's something else you can try.
Try using a functor.  A functor is a class that acts like a function.
Example:
template<class T>
class randomItem
{
public:
     T operator ()(int len)
     {
          return (T)0;
     }
     int len;
};

//specialization for int
//this function returns a random number of length len
template<>
int randomItem<int>::operator()(int len)
{
    return 0;
}

//specialization for char*
//this function returns a random string of length len
template<>
char* randomItem<char*>::operator()(int len)
{
    return NULL;  
}

int main(int argc, char* argv[])
{
     int x = randomItem<int>()(3);  //Notice the extra () before the argument
     char* xc = randomItem<char*>()(5);//extra () before the argument
     return 0;
}


With the above method, you don't need a dummy variable.
0
 
LVL 30

Expert Comment

by:Axter
ID: 6454389
Correction:
In the above template class, I forgot to remove the "int len" member data.
It should be the following:

template<class T>
class randomItem
{
public:
    T operator ()(int len)
    {
         return (T)0;
    }
};
0
 
LVL 30

Expert Comment

by:Axter
ID: 6454414
My last suggestion is to use a regular template class with an operator T() function.

Example:

template<class T>
class randomItem
{
public:
     randomItem(int len_input):len(len_input){}
     operator T()
     {
          return (T)0;
     }
     int len;
};

//specialization for int
//this function returns a random number of length len
template<>
randomItem<int>::operator int()
{
    return 0;
}

//specialization for char*
//this function returns a random string of length len
template<>
randomItem<char*>::operator char*()
{
    return NULL;  
}

int main(int argc, char* argv[])
{
     int x = randomItem<int>(3);
     char* xc = randomItem<char*>(5);
     return 0;
}

Using this method, you can still use the class like a function, and the return type will be what ever you use in the template argument (<int>)........
0

Featured Post

On Demand Webinar - Networking for the Cloud Era

This webinar discusses:
-Common barriers companies experience when moving to the cloud
-How SD-WAN changes the way we look at networks
-Best practices customers should employ moving forward with cloud migration
-What happens behind the scenes of SteelConnect’s one-click button

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

730 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question