Solved

Template Function Specialization

Posted on 2001-09-04
15
377 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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
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

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

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

Suggested Solutions

In days of old, returning something by value from a function in C++ was necessarily avoided because it would, invariably, involve one or even two copies of the object being created and potentially costly calls to a copy-constructor and destructor. A…
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 tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

860 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