template functions and STL list.sort

Started by
31 comments, last by lightxbulb 10 years, 10 months ago

Hi!

With C++ I've currently gotten to the part where I am learning different STL containers. I've been playing around with lists but I get an error, I just want to know why do I get an error when I do this:


template <typename T>
bool sortDescending(const T& in1, const T& in2)
{
    return in1>in2;
}

and then I just try to sort some list with it:


myList.sort(sortDescending);

If I change my sort function it's all fine:


bool sortDescending(const int& in1, const int& in2)
{
    return in1>in2;
}

Can anybody explain why exactly C++ forbids me from writing a more generic sort function?

Advertisement

You can write a generic template sorting function, but you have to instantiate it with the proper type when you pass it to the sort function. The C++ type system cannot deduce the template parameter in that case so you have to provide it.

myList.sort(sortDescending<int>);

Have you defined operator> for T? It's already defined for ints ;)

EDIT: What Brother Bob said as well ;)

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

I am not sure I can explain the exact reason for that being disallowed, but I can tell you how to fix it:


myList.sort(sortDescending<int>);

Now I'll try to explain it anyway. The compiler tries to figure out the type of what you are passing to std::list<int>::sort, and it can't figure it out because you are passing something with an "unresolved overloaded function type" (that's what the error message in g++ calls it). If you specify sortDescending<int>, now the compiler knows the type being passed and can continue to figure out what version of the overloaded std::list<int>::sort you are calling.

EDIT: Double ninja'd. I must be getting slow. :)

Or you could save some typing and use

myList.sort(std::greater<int>);

EDIT: Although you probably have to type #include <functional> as well...

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Thanks a lot guys!

Guess it's just me then not being used to templates xD

Even though it looks logical (to me) that the compiler will infer the evaluated type of the variables from the type of objects contained in the list, I guess it's not.

I mean the compiler usually will be able to "guess" what s the type if I write:


template <typename T>
bool greaterThan(const T& in1, const T& in2)
{
return in1>in2;
}

and:


int a=5, b=6;
cout << greaterThan(a,b) << endl; 

No error in this one...

Btw that's a little off-topic but can anybody with a C++11 compiler tell me if this works for him:


vector<int> myVec = {5, 13, -7};

C++ 11 should support it right? I'm on VS2012 and it seems it doesn't support some of the features for C++ 11.

Not according to this (confusing, VS2010 is called VC10 and VS2012 is called VC11) page: http://msdn.microsoft.com/en-us/library/vstudio/hh567368.aspx

I know they released a C++11 features update but I don't know whether initializer lists made it in.

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

It just seems silly being able to do this:


int someArray[] = {3, 5 -17};
vector <int> someVector(someArray, someArray + sizeof(someArray) / sizeof(int));

and not this:


vector<int> someVector = {3, 5, -17};

It took years for it to get into the language that feature though. And you have extra baggage associated with those (initializer_list<> template class).

You should use sizeof(someArray) / sizeof(someArray[0]) as well in your first example (in case you change the type of the array to something other than int).

"Most people think, great God will come from the sky, take away everything, and make everybody feel high" - Bob Marley

Thanks a lot guys!

Guess it's just me then not being used to templates xD

Even though it looks logical (to me) that the compiler will infer the evaluated type of the variables from the type of objects contained in the list, I guess it's not.

I mean the compiler usually will be able to "guess" what s the type if I write:


template <typename T>
bool greaterThan(const T& in1, const T& in2)
{
return in1>in2;
}

and:


int a=5, b=6;
cout << greaterThan(a,b) << endl; 

No error in this one...

There's a major difference between that example and deducing the argument of the predicate in your first post. The template parameter of greaterThan is deduced from the parameters being passed to it, while you expected that the template parameter of sortDescending to be deduced from the type of the parameter of another function to which the predicate is passed.

This topic is closed to new replies.

Advertisement