Template tricks and examples

Pages: 123
Consider the following code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
template<typename T>
class Shell {
public:
	template<int N>
	class In {
	public:
		template<int M>
		class Deep {
		public:
			virtual void f();
		};
	};
};


template<typename T, int N>
class Weird 
{
public:
	void case1(typename Shell<T>::template In<N>::template Deep<N>* p) 
	{
		p->typename Deep<N>::f(); // EDITED TO typename
	}
	void case2(typename Shell<T>::template In<T>::template Deep<T>& p) 
	{
		p.typename Deep<N>::f(); // EDITED TO typename
	}
};



You have to agree that not many people would know that, I'm just currious if there is more such sintactic sugars...

If you have any example please post it here :)

Edited to typename
Last edited on
closed account (1yR4jE8b)
I have no idea what the heck is going on here...

Shell<T>::template In<N>::template Deep<N>* p

Dafuq?!
1
2
3
4
void case1(typename Shell<T>::template In<N>::template Deep<N>* p) 
{
	p->typename Deep<N>::f(); // EDITED to typename
}


The class Weird Has no clue that nested classes In and Depp are templates them self.

that means the compiler will give you and error cos it dosn't know as well that these nested classes are templates.

To solve the problem you have to explicitly "tell the compiler" that these classes are templates.

to do you type template before template name and argument list like:
template In<T>

Even if you do so You will still get an compile time error cos compiler has no clue that this is a typename so you have to type typename at begining of declaration like:
typename Shell<T>

finaly you have to repeat that process for every typename, that is:
typename Shell<T>::template In<N>::template Deep<N>*

Which tells the compiler that Depp<N>* is a typename, in this case pointer to the type N

Still you didn't solve the proble and you'll still get compile time error within funcion it self!

p-> Deep<N>::f() // error

compiler has no clue that this is an template.

so you have to tell him explicitly that this is a template by doing so:
p->typename Deep<N>::f(); // EDITED to typename

Which is self explanatory, f() is a class mehtod of templated class Deep<N>

Finaly you have a mehtod:
1
2
3
4
void case1(typename Shell<T>::template In<N>::template Deep<N>* p) 
{
	p->typename Deep<N>::f();  // EDITED to typename
}


Which means the following:

function takes a pointer to the double nested class of type Deep<N> and it exectutes it's class method f().

Edited to replace template with typename

Last edited on
Question: why?
This doesn't look quite right - I think I'm going to try it.
ButI can't see what trick they are trying to pull off here - seems just like nested class stuff to me - but I'll look harder.
Gaminic,
What you mean?

guestgulkan,
actually this works as it is,

for example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
using std::cout;
using std::endl;

template<typename T>
class Shell {
public:
	template<int N>
	class In {
	public:
		template<int M>
		class Deep {
		public:
			virtual void f() { cout << "I'm your night mare"; }
		};
	};
};


template<typename T, int N>
class Weird 
{
public:
	void case1(typename Shell<T>::template In<N>::template Deep<N>* p) 
	{
		p->typename Deep<N>::f();
	}
};


Shell<int>::template In<3>::template Deep<3> object;
Weird<int, 3>* testobject;

int main()
{
	testobject = new Weird<int, 3>;
	object.f();
	cout << endl;
	testobject->case1(&object);
	delete testobject;
	return 0;
}


I removed p->template Deep<N>::f(); cos it gived me an error in visual studio, I don't know why though? as that was the correct sintax.

Silly me it should be typename instead Sorry!
Last edited on
Why would you do this? What is this "trick" doing? What exactly are you trying to show?
Gaminic wrote:
Why would you do this? What is this "trick" doing? What exactly are you trying to show?

... that C++ is full of kludges, meant for abusing its own features in as verbose a manner as possible?
Gaminic,
My intention was to open a topic to talk about templates.

this trick actually does not do anthing special, I wanted to show the sintax used in such cases which is not very well known because such constructs are rarley used.

Sitll if any of you guys have a similar stuff to show then post it.
Not what I was expecting when I came in here. The only templates I learned from my CS book were the basic like this:
1
2
3
4
5
6
7
8
template <class Type>
Type larger(Type x, Type y)
{
      if (x >= y)
            return x;
      else
            return y;
}

So all that takes a little more to understand for me as my book never went really far beyond that example I just put.
closed account (zb0S216C)
The problem with these so-called "tricks" is that they only offer obscurity. Yeah, they may help the programmer in some way, but risk confusing anyone who reads the code. Therefore, I avoid "tricks".

codekiddy wrote:
"which is not very well known because such constructs are rarley used"

For a very good reason: It's useless.

To be perfectly honest, codekiddy, I have absolutely no idea what your "trick" is supposed to do. I mean, if I wanted to reach the f() function, I would have to:

1) Qualify f() with Deep<T>, then...
2) Qualify Deep<T> with In<T>, followed by...
3) The qualification of In<T> with Shell<T>

It's just unnecessary and offers nothing in terms of functionality, or even usefulness in general. This isn't a "trick".

Wazzak
codekiddy wrote:
Gaminic,
My intention was to open a topic to talk about templates.

this trick actually does not do anthing special, I wanted to show the sintax used in such cases which is not very well known because such constructs are rarley used.

Sitll if any of you guys have a similar stuff to show then post it.
closed account (zb0S216C)
I do have a trick actually, well, it's not really a trick, but it looks like one:

1
2
3
4
5
6
7
8
9
10
11
12
13
void Print(int *Array);

int main()
{
    Print((int[]){1, 2, 3, 4, 0});

    return(0);
}

void Print(int *Array)
{
    while(*Array) std::cout << *(Array++) << " ";
}

Wazzak
Only problem. What if something directly after your array's memory location contains something other than 0? Also, it couldn't print anything with a 0 midway through it.
Last edited on
closed account (zb0S216C)
Whovian wrote:
"What if something directly after your array's memory location contains something other than 0? Also, it couldn't print anything with a 0 midway through it."

Use your nut:

1
2
3
4
5
6
7
class A
{
    public:
        operator bool() const { return(this->A__); }
    private:
        int A__;
};


Besides, no one said the trick must work, or even must be flexible.

Wazzak
1
2
3
4
5
6
int main()
{
    Print((int[]){1, 2, 3, 4, 0});

    return(0);
}


This is not a valid C++ code, moreover I'm pretty sure that this does compile at all.

also when I mentioned "template tricks" I didn't mean on something that is not valid C++ or something that is useless rarley used like goto statement for example.

edit:
1
2
3
4
void Print(int *Array)
{
    while(*Array) std::cout << *(Array++) << " ";
}


Also result of this method is undefined.


Last edited on
Also result of this method is undefined.


How so?
closed account (zb0S216C)
codekiddy wrote:
"This is not a valid C++ code"

Why is valid code invalid? Why don't you try to compile the following code. I'll assure you that the first statement is valid, whereas the second is not.

1
2
3
4
5
int main()
{
    (int[]){1, 2, 3};
    int [] = {1, 2, 3};
}


codekiddy wrote:
"moreover I'm pretty sure that this does compile at all"

It does compile.

codekiddy wrote:
"Also result of this method is undefined."

It is defined. Also, how do you know? Judging by what you've just said, you haven't even tried compiling it.

Wazzak

Last edited on
Ok, here is what I got testing this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void Print(int *Array)
{
	while(*Array) cout << *(Array++) << "\n";
}

int main()
{
	int y[] = {0,1,2,3};
	int x[4] = {0,1,2,3};
	int* z = new int(4);

	// THE RESULTS
	Print(y);		// It prints nothing
	Print(x);		// It prints nothing
	Print(z);		// It prints number 4 + garbage 5 times in a row
	Print((int[]){1, 2, 3, 4, 0}); // ERROR incomplete type is not allowed + expected an expression

	delete z;
	return 0;
}
closed account (zb0S216C)
Clearly, you don't understand how my Print() function works. And yet, you question it.

Wazzak
Pages: 123