Solved

Template Function Specialization

Posted on 2001-09-04
15
373 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
  • 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
 
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
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 

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

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

When writing generic code, using template meta-programming techniques, it is sometimes useful to know if a type is convertible to another type. A good example of when this might be is if you are writing diagnostic instrumentation for code to generat…
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 viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

760 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

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now