tags:

views:

211

answers:

5

I don't understand templates really and was trying to run a simple find the minimum for ints, doubles, chars.

First question, why is template<typename T> sometimes used, and other times template<>?

Second question, I do not know what I am doing wrong with the following code below:

#include <iostream>

template <typename T>
T minimum(T arg1, T arg2)
{
    return arg1 < arg2 ? arg1 : arg2;
}

template <typename T>
// first I tried template <> instd of above, but wasn't sure the difference
T minimum<const char *>(const char *arg1, const char *arg2)
{
    return strcmp(arg1, arg2) ? arg2 : arg1;
}

int main()
{
    std::cout << minimum<int>(4, 2) << '\n';
    std::cout << minimum<double>(2.2, -56.7) << '\n';
    std::cout << minimum(2.2, 2) << '\n';
}

Compile Errors:
 error C2768: 'minimum' : illegal use of explicit template arguments
 error C2783: 'T minimum(const char *,const char *)' : could not deduce template argument for 'T'
 : see declaration of 'minimum'
 : error C2782: 'T minimum(T,T)' : template parameter 'T' is ambiguous
 : see declaration of 'minimum'

Third, in getting familiar with separating .h and .cpp files, if I wanted this minimum() function to be a static function of my class, but it was the only function in that class, would I have to have a template class as well? I originally tried doing it that way instead of having it all in one file and I got some compile errors as well that I can't remember right now and was unsure how I would do that. Thanks!

+2  A: 

Try this:

template <>
const char* minimum<const char *>(const char *arg1, const char *arg2)
{
    return strcmp(arg1, arg2) ? arg2 : arg1;
}
Torlack
Can templates have different return types? I tried that and got this error: error C2782: 'T minimum(T,T)' : template parameter 'T' is ambiguous1> see declaration of 'minimum'1> could be 'int'1> or 'double'
Crystal
Did you try my code? Your original had "T" as the return type in the original specialization.
Torlack
+6  A: 

It sounds like you need to get (and study) a book the covers templates -- it looks like you need to learn far too much of the basics to cover in an answer here.

The template<> syntax is used for template specialization. For what you apparently want, you'd do something like this:

template <class T>
T minimum(T const &a, T const &b) {
    return a < b ? a : b;
}

template<>
char const *minimum<char const *>(char const *a, char const *b) { 
    return strcmp(a, b) ? a : b;
}

Generally speaking, however, this is really the wrong thing to do -- instead of providing specializations for char const *, you usually want to just use std::string, which provides an operator< so your first version would work.

Jerry Coffin
+2  A: 

Lets tackle that first question. You want to review Template Specialization, and it was your syntax that was off:

#include <iostream>

template <typename T>
T minimum(T arg1, T arg2)
{
    return arg1 < arg2 ? arg1 : arg2;
}

template<> const char * minimum<const char *>(const char *arg1, const char *arg2)
{
    return strcmp(arg1, arg2) ? arg2 : arg1;
}

int main()
{
    std::cout << minimum<int>(4, 2) << '\n';
    std::cout << minimum<double>(2.2, -56.7) << '\n';
    std::cout << minimum(2.2, 2.0) << '\n';
}

Once you wrap your head around that, I bet you can get the rest to work.

qor72
+1  A: 

Your const char* specialization is incorrect. You have it return any type T. This is not supported by your function which returns a const char*. Basically you can't half do the specialization either T is specialized or it isn't. If it is specialized then it shouldn't appear in the template<> list. If it isn't specialized then it should be in the template list.

stonemetal
+2  A: 

It looks like your question is almost answered, but you still have a couple of outstanding issues...

std::cout << minimum(2.2, 2) << '\n';

This won't compile with the two template functions you have provided as there is no matching function for call to minimum(double, int). This leaves you two options:

You can change your first template function to be:

template <typename T, typename U>
T minimum(T arg1, U arg2)
{
    return arg1 < arg2 ? arg1 : arg2;
}

or

You can change your code to specify which specialisation to invoke:

std::cout << minimum<double>(2.2, 2) << '\n';

There is also a bug in your const char* specialisation (once the syntax error is resolved) since a zero return value from strcmp indicates that both strings are equal. The following assertion will fail:

assert(0 == strcmp("aaa", minimum("aaa", "bbb")));

This can be fixed thus:

template <>
const char* minimum<const char*>(const char* arg1, const char* arg2)
{
    return strcmp(arg1, arg2) > 0 ? arg2 : arg1;
}
Johnsyweb
Sorry for my ignorance, but I don't quite see how it fails. You are correct that it does when I checked it with aaa and bbb, but I don't see why.... Thanks.
Crystal
nm, got it. thanks!
Crystal