Template Function Specialization

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.  
industrycityAsked:
Who is Participating?
 
AxterConnect With a Mentor Commented:
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
 
AxterCommented:
You can not do specialization for return type only.
0
 
AxterCommented:
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
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

 
AxterCommented:
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
 
AxterCommented:
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
 
industrycityAuthor Commented:
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
 
industrycityAuthor Commented:
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
 
industrycityAuthor Commented:
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
 
industrycityAuthor Commented:
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
 
industrycityAuthor Commented:
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
 
udilCommented:
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
 
industrycityAuthor Commented:
You solved a real vexing problem that was driving me crazy.  Thanks a lot.
0
 
AxterCommented:
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
 
AxterCommented:
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
 
AxterCommented:
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
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.