Template tricks and examples

Pages: 123
Clearly, you don't understand how my Print() function works. And yet, you question it.


Actually I do know how your funtion work.
Since this is a thread about templates I take a freedom to implement a template to solve your "so called trick"

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
template<typename E, int N>
void Print(E(&b)[N])
{
	for(int i = 0; i < sizeof(b) / sizeof(N); ++i)
		cout << b[i] << "\n";
}

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

	// THE RESULTS
	Print(y);		// NOW IS OK
	Print(x);		// NOW IS OK


	// this stil does not compile
	Print((int[]){1, 2, 3, 4, 0}); // ERROR incomplete type is not allowed + expected an expression

	return 0;
}
Last edited on
closed account (zb0S216C)
codekiddy wrote:
"Actually I do know how your funtion work."

No, you don't. If you did, you'd understand why my Print() function displayed nothing when you passed both x & y to it.

What compiler are you using?

Wazzak
Print((int[]){1, 2, 3, 4, 0}); // ERROR incomplete type is not allowed + expected an expression

I actually get:

Error	1	error C2143: syntax error : missing ')' before '{'	c:\users\firedraco\documents\visual studio 2008\projects\sandbox\sandbox\main.cpp	9
Error	2	error C2059: syntax error : ')'	c:\users\firedraco\documents\visual studio 2008\projects\sandbox\sandbox\main.cpp	9
Error	3	error C2143: syntax error : missing ';' before '{'	c:\users\firedraco\documents\visual studio 2008\projects\sandbox\sandbox\main.cpp	9
Error	4	error C2143: syntax error : missing ';' before '}'	c:\users\firedraco\documents\visual studio 2008\projects\sandbox\sandbox\main.cpp	9
Error	5	error C2059: syntax error : ')'	c:\users\firedraco\documents\visual studio 2008\projects\sandbox\sandbox\main.cpp	9
firedraco,

Yes I'm geting the same compile errors, but intelisence gives me another type of error which is commented out in my post abowe.

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};
}


I'm truly sorry man but none of above constructs work on my compiler which is VC++, Visual studio beta 11

I have a fealing that you are shooting into C++11 which does not maybe work yet, if so please provide a reference as I would like to learn that.
closed account (zb0S216C)
That's why then; I'm using MinGW.

Wazzak
Last edited on
p->typename Deep<N>::f();
error: expected unqualified-id before ‘typename’
error: expected ‘;’ before ‘typename
However p->f(); works fine.

Shell<int>::template In<3>::template Deep<3> object;
error: ‘template’ (as a disambiguator) is only allowed within templates
It should be just Shell<int>::In<3>::Deep<3>

¿why are you making testobject a pointer?


1
2
3
4
5
6
7
template<typename E, int N>
void Print(E(&b)[N])
{
	//for(int i = 0; i < sizeof(b) / sizeof(N); ++i)
	for(int i = 0; i < N; ++i)
		cout << b[i] << "\n";
}
But Framework wanted to use a sentinel.

http://www.cplusplus.com/forum/general/27880/#msg149659
¿thoughts?
Last edited on
It should be just Shell<int>::In<3>::Deep<3>
Sorry, This does not work with VC++ edit: I though you talk about function paramenters within a class, but anyway both approaches work and are valid C++.

However p->f(); works fine.

as well as
p->typename Deep<N>::f(); works as well and is valid C++, but yes it's not needed here in this case.


Last edited on
Wow, this got pretty cut-throat.
By far the most useful thing you could ever do:
1
2
3
4
5
6
7
8
9
10
11
12
class MyClass
{
    //...
public:
    //...
    template<typename T>
    operator T()
    {
        return T(*this);
    }
    //...
};
<_<
/me looks up at the stratosphere of geek speak and wishes he understood :(

I fear templates are over my head right now.
Framework wrote:
I do have a trick actually, well, it's not really a trick, but it looks like one:
Print((int[]){1, 2, 3, 4, 0});


Since nobody mentioned what this was yet, this is a bit of C (C99 specifically) that's not valid C++. It's called "compound literal".

GCC allows it (just like it allows variable-length arrays, another C-only feature) unless standard conformance is requested.
Last edited on
(Props L B!)
BHXSpecter wrote:
/me looks up at the stratosphere of geek speak and wishes he understood :(

I fear templates are over my head right now.


Actually, they're not that much different than functions, and have been described as "glorified macros," though I strongly disagree, but they are similar in some respects to safer preprocessor macros. A full understanding of them would probably come after Object-oriented programming, but once you've learned that, I'd say templates won't be too hard.
The problem with templates is that most compilers still don't know how to print sane error messages for them.
hanst99,

That is completely true,

For example this code will work on with VC++ v100 but will NOT work with VC++ v110
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
template<typename T>
class Outer 
{
public:
	template<typename U>
	class Inner 
	{
	private:
		static int count;
	};

	static int code;
	void print() const
	{
		std::cout << "outer";
	}
};

template<typename T>
int Outer<T>::code = 0;

template<typename T>
template<typename U>
int Outer<T>::Inner<U>::count = 0;

template<>
template<>
class Outer<bool>::Inner<bool> 
{
public:
	static int count;
};

// ERROR in Visual studio 11, OK in Visual studio 10
int Outer<bool>::Inner<bool>::count = 4; // ERROR in VC++ 11 


Why new platform toolset does not work and old one works? only good knows...
Completely true. I've even heard the error messages compared to staring into the sun. Unfortunately, I tried and have had trouble producing an error message for one for some reason.
Last edited on
Completely true. I've even heard the error messages compared to staring into the sun. Unfortunately, I tried and have had trouble producing an error message for one for some reason.


Thanks. This is one of those rare times when I feel useful.

1
2
3
4
5
6
7
8
#include <set>

int main()
{
	std::set<signed int> s;

	for (std::set<unsigned int>::const_iterator ci = s.begin(); ci != s.end(); ++ci);
}


terror.cpp: In function ‘int main()’:
terror.cpp:7:59: error: conversion from ‘std::set<int>::iterator {aka std::_Rb_tree_const_iterator<int>}’ to non-scalar type ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ requested
terror.cpp:7:74: error: no match for ‘operator!=’ in ‘ci != s.std::set<_Key, _Compare, _Alloc>::end<int, std::less<int>, std::allocator<int> >()’
terror.cpp:7:74: note: candidates are:
In file included from /usr/include/c++/4.7/set:60:0,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_tree.h:301:7: note: bool std::_Rb_tree_const_iterator<_Tp>::operator!=(const _Self&) const [with _Tp = unsigned int; std::_Rb_tree_const_iterator<_Tp>::_Self = std::_Rb_tree_const_iterator<unsigned int>]
/usr/include/c++/4.7/bits/stl_tree.h:301:7: note:   no known conversion for argument 1 from ‘std::set<int>::iterator {aka std::_Rb_tree_const_iterator<int>}’ to ‘const _Self& {aka const std::_Rb_tree_const_iterator<unsigned int>&}’
In file included from /usr/include/c++/4.7/set:62:0,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_multiset.h:709:5: note: template<class _Key, class _Compare, class _Alloc> bool std::operator!=(const std::multiset<_Key, _Compare, _Alloc>&, const std::multiset<_Key, _Compare, _Alloc>&)
/usr/include/c++/4.7/bits/stl_multiset.h:709:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::multiset<_Key, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/set:61:0,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_set.h:728:5: note: template<class _Key, class _Compare, class _Alloc> bool std::operator!=(const std::set<_Key, _Compare, _Alloc>&, const std::set<_Key, _Compare, _Alloc>&)
/usr/include/c++/4.7/bits/stl_set.h:728:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::set<_Key, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/set:60:0,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_tree.h:883:5: note: template<class _Key, class _Val, class _KeyOfValue, class _Compare, class _Alloc> bool std::operator!=(const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&, const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>&)
/usr/include/c++/4.7/bits/stl_tree.h:883:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>’
In file included from /usr/include/c++/4.7/set:60:0,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_tree.h:315:5: note: template<class _Val> bool std::operator!=(const std::_Rb_tree_iterator<_Tp>&, const std::_Rb_tree_const_iterator<_Val>&)
/usr/include/c++/4.7/bits/stl_tree.h:315:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::_Rb_tree_iterator<_Tp>’
In file included from /usr/include/c++/4.7/bits/stl_tree.h:64:0,
                 from /usr/include/c++/4.7/set:60,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/allocator.h:134:5: note: template<class _Tp> bool std::operator!=(const std::allocator<_Tp1>&, const std::allocator<_Tp1>&)
/usr/include/c++/4.7/bits/allocator.h:134:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::allocator<_Tp1>’
In file included from /usr/include/c++/4.7/bits/stl_tree.h:64:0,
                 from /usr/include/c++/4.7/set:60,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/allocator.h:129:5: note: template<class _T1, class _T2> bool std::operator!=(const std::allocator<_T1>&, const std::allocator<_T2>&)
/usr/include/c++/4.7/bits/allocator.h:129:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::allocator<_T1>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/set:60,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:355:5: note: template<class _IteratorL, class _IteratorR> bool std::operator!=(const std::reverse_iterator<_IteratorL>&, const std::reverse_iterator<_IteratorR>&)
/usr/include/c++/4.7/bits/stl_iterator.h:355:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::reverse_iterator<_IteratorL>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:68:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/set:60,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_iterator.h:305:5: note: template<class _Iterator> bool std::operator!=(const std::reverse_iterator<_Iterator>&, const std::reverse_iterator<_Iterator>&)
/usr/include/c++/4.7/bits/stl_iterator.h:305:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::reverse_iterator<_Iterator>’
In file included from /usr/include/c++/4.7/bits/stl_algobase.h:65:0,
                 from /usr/include/c++/4.7/bits/stl_tree.h:63,
                 from /usr/include/c++/4.7/set:60,
                 from terror.cpp:1:
/usr/include/c++/4.7/bits/stl_pair.h:225:5: note: template<class _T1, class _T2> bool std::operator!=(const std::pair<_T1, _T2>&, const std::pair<_T1, _T2>&)
/usr/include/c++/4.7/bits/stl_pair.h:225:5: note:   template argument deduction/substitution failed:
terror.cpp:7:74: note:   ‘std::set<unsigned int>::const_iterator {aka std::_Rb_tree_const_iterator<unsigned int>}’ is not derived from ‘const std::pair<_T1, _T2>’

Why are you mismatching signed/unsigned?

1
2
3
4
5
6
7
8
#include <set>

int main()
{
	std::set<signed int> s;

	for (std::set<int>::const_iterator ci = s.begin(); ci != s.end(); ++ci);
}


1>Build succeeded.
1>
1>Time Elapsed 00:00:01.73
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
Last edited on
Because he wanted to demonstrate how a template error looks like?
Pages: 123