template functions and STL list.sort

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

Some of this missing functionality has been "emulated" to a reasonable degree in the standard library for some time though (e.g. variadic templates), which at least allowed you to start writing client code in a way that will leverage the proper features when they are added in.

This feature gave rise to my favourite quote from the MSDN:

"Therefore, we reduced infinity. In Visual C++ 2008 SP1 and Visual C++ 2010, infinity was 10 (that is, "variadic" templates supported 0 to 10 arguments, inclusive). By default, infinity is 5 in Visual C++ in Visual Studio 2012."

EDIT: Infinity is 10... no, it's 5... for small values of infinity.

Yes, that's a good one. IIRC, in 2012 at least, the value of 'Infinity' can at least be redefined if you need (although it's not 'supported', its supposed to work for reasonably large values of 'Infinity'). It has a default that's fairly small, I think, but its more about compile-time performance than the capabilities of the template magic going on behind the scenes. I'm pretty sure you can go higher than 10 in VS2012, as long as you can live with the compile times.

The situation is less than optimal, but for most client code 'Infinity' in a range of 5-10 is alright. In general, the people who really need *real* variadic templates or even 'Infinities' larger than 5-10 are library writers and maintainers, not library users. It could be better, but the work around at least satisfies the 80/20 rule.

throw table_exception("(? ???)? ? ???");

Advertisement

<offtopic>

The infinity thing is even better than my second favourite quote from the MSDN:

"If you are a developer who implements toast-like functionality in one of your products, you are encouraged to use the ToastSemaphore mutex to avoid toast collisions."

</offtopic>

EDIT: Is it a semaphore? Is it a mutex? NO! It's the ToastSemaphore mutex ;)

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

Of course I am not passing a template class to the display() function, but the parameter for the display function can accept multiple specializations of a template.

I wanted to know if the same is possible for a function - here's some code to illustrate this:


template <typename T>
void someFunction(const T& input)
{
	//do sth
}

template <typename T>
class SomeClass
{

};

...

SomeClass<int> myClass;

someFunction(myClass);

and I guess it's not possible the same for a function?


template <typename T>
class someContainer
{
public:
	void sort(bool(*inputFunction)(T&,T&)) //I know you can't pass a function like this
        //I was just thinking that it would be nice if you could - or would it "break" something?
        //something like a default parameter for the template but in a function parameter
	{
		//do sth
		inputFunction<R>(...);
		//do sth
	}
};

template <typename T>
void someFunction(T& input1, T& input2)
{
	//do sth
}

The 2nd code won't work don't even try it - it's there just to illustrate what I had in mind...

Btw would it work with a functor?

P.S. And thanks a lot about the info on C++ 11 ParadigmShifter, I just don't have any more rep points to give for today so I can't rep you - sorry.

But that example is about what I'm trying to say; you cannot compare the two because in the first case you fully instantiate the template and pass it, but in the second case you pass a template and expect the receiver to instantiate it for you. It's fine to pass instantiated function templates, just as you showed that you can pass instantiated template classes, but passing function templates and class templates and have the receiver instantiate them is something completely different.

In your first example the function adapts itself based on the parameter, but in the second example you expect the function to adapt the parameter.

Uh this works fineblink.png :


#include <iostream>
using namespace std;

template <typename T>
class SomeContainer
{
private:
	T val1;
	T val2;
public:
	SomeContainer(const T& in1, const T& in2)
		: val1(in1), val2(in2) {}

	void sort( bool (*func)(const T&, const T&))
	{
		func(val1, val2);
		return;
	}

};

template <typename R>
bool someFunction(const R& input1,const R& input2)
{
	cout <<input1 << ' ' << input2 << endl;
	return 0;
}

int main()
{
	SomeContainer<int> my(5,4);
	my.sort(someFunction);

	cin.ignore();
	return 0;
}

That sort function does not take a template type. Once the SomeContainer template is instantiated with the type int (by making an object of type SomeContainer<int>), its sort function is defined to take a function pointer of type bool(int const &, int const &) and nothing else. That is different from std::list::sort which in itself is a template function inside the template class std::list.

Yeah my idea is what is exactly so different - I want to understand the whole thing in depth. Do you know where I can find the corresponding source code file to the <list> header so I can check its internal mechanics?

In Visual studio, right click on list and go to definition, works for me.

EDIT: list variable definition that is. You can probably open the header by right clicking on the #include <list> though too.

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

Likely where you have installed your compiler. If you have a decent IDE, you may even be able to open it by just right-clicking the file name in an #include statement or something.

edit: beaten, that's what happens when you wait with submitting the post for no good reason...

Thanks - though it sends me at the header, but I think I'll find what I'm looking for there(I think the cpp is compiled already).

I suppose I should be looking at this blink.pngunsure.png :


	template<class _Pr2>
		void sort(_Pr2 _Pred)
		{	// order sequence, using _Pred
		if (2 <= this->_Mysize)
			{	// worth sorting, do it
			const size_t _MAXBINS = 25;
			_Myt _Templist(this->_Getal()), _Binlist[_MAXBINS + 1];
			size_t _Maxbin = 0;

			while (!empty())
				{	// sort another element, using bins
				_Templist._Splice_same(_Templist.begin(), *this, begin(),
					++begin(), 1);

				size_t _Bin;
				for (_Bin = 0; _Bin < _Maxbin && !_Binlist[_Bin].empty();
					++_Bin)
					{	// merge into ever larger bins
					_Binlist[_Bin].merge(_Templist, _Pred);
					_Binlist[_Bin].swap(_Templist);
					}

				if (_Bin == _MAXBINS)
					_Binlist[_Bin - 1].merge(_Templist, _Pred);
				else
					{	// spill to new bin, while they last
					_Binlist[_Bin].swap(_Templist);
					if (_Bin == _Maxbin)
						++_Maxbin;
					}
				}

			for (size_t _Bin = 1; _Bin < _Maxbin; ++_Bin)
				_Binlist[_Bin].merge(_Binlist[_Bin - 1],
					_Pred);	// merge up

			_Analysis_assume_(0 < _Maxbin);

			splice(begin(), _Binlist[_Maxbin - 1]);	// result in last bin
			}
		}

/*
 * This file is derived from software bearing the following
 * restrictions:
 *
 * Copyright (c) 1994
 * Hewlett-Packard Company
 *
 * Permission to use, copy, modify, distribute and sell this
 * software and its documentation for any purpose is hereby
 * granted without fee, provided that the above copyright notice
 * appear in all copies and that both that copyright notice and
 * this permission notice appear in supporting documentation.
 * Hewlett-Packard Company makes no representations about the
 * suitability of this software for any purpose. It is provided
 * "as is" without express or implied warranty.
 */

And the function pointer or functor is actually _Pr2 Pred?

The code is likely there; it's a template and templates cannot generally be pre-compiled. Generally I say, because you can instantiate templates and pre-compile them but I find it unlikely in this case. The code you're looking for is probably there, or in some other file included by that header.

This topic is closed to new replies.

Advertisement