Can I define my own template functions?
Can I define my own template functions?
Greetings!
As subjected,if yes,any special concerns should I pay attention to?
Thanks and best regards,
Sam
As subjected,if yes,any special concerns should I pay attention to?
Thanks and best regards,
Sam
Re: Can I define my own template functions?
Hi Sam,
At the moment, eC only have support for class generics.
It is (to some extent) still an experimental feature, and mainly meant to power the type-aware containers (e.g. Array, List, AVLTree, Map...) and Iterator, which provide equivalent functionality to many of the C++ STL classes.
Please read the Templates section in this original blog post for the new feature:
http://www.ecere.com/blog/2008/09/03/ec ... hlighting/
There are 3 types of parameterization possible for classes, being:
- A generic type
- A generic identifier, meant to be a member of a class
- A generic value
You can find examples for the first one (generic type) in all of the ecere source tree's containers (sdk/ecere/src/com/containers). Be aware that it is still experimental and may suffer from some limitations.
The latter 2 are used for the LinkList class (also in that folder).
The LinkList class is a generic link list linking nodes which contain within themselves both a previous and next link member. It uses the generic identifier to define an arbitrary member of the class to serve as the previous and next links. The generic value is used to specialize the link list as either circular or not. These features are only used in the LinkList, and are thus particularly experimental/limited.
As a quick overview, here's some things you can do with a generic class:
Again be warned: if you use these features, you may come across limitations (e.g. using it in certain way might crash). There are often ways to work around it, but still if you do, please take the time to report an issue on Mantis so that we can improve the support for these generics! If there is something in particular which you would like to do but cannot work around, please let me know and I will try to suggest a work around and/or prioritize a fix in the compiler.
Best regards,
Jerome
At the moment, eC only have support for class generics.
It is (to some extent) still an experimental feature, and mainly meant to power the type-aware containers (e.g. Array, List, AVLTree, Map...) and Iterator, which provide equivalent functionality to many of the C++ STL classes.
Please read the Templates section in this original blog post for the new feature:
http://www.ecere.com/blog/2008/09/03/ec ... hlighting/
There are 3 types of parameterization possible for classes, being:
- A generic type
- A generic identifier, meant to be a member of a class
- A generic value
You can find examples for the first one (generic type) in all of the ecere source tree's containers (sdk/ecere/src/com/containers). Be aware that it is still experimental and may suffer from some limitations.
The latter 2 are used for the LinkList class (also in that folder).
The LinkList class is a generic link list linking nodes which contain within themselves both a previous and next link member. It uses the generic identifier to define an arbitrary member of the class to serve as the previous and next links. The generic value is used to specialize the link list as either circular or not. These features are only used in the LinkList, and are thus particularly experimental/limited.
As a quick overview, here's some things you can do with a generic class:
Code: Select all
class MyClass<class T>
{
T what;
void DoStuff(T something)
{
what = something;
PrintLn(something);
}
}
void Test()
{
MyClass<int> a { };
a.DoStuff(30);
}
Best regards,
Jerome
Re: Can I define my own template functions?
As an exercise,I've tried to implement a generic data structure Stack.First I wrote a plain version for int,given below code:
The running result was as expected.Except there is a surprise worth to question:
the private field top should not be accessed outside,am I right?But in the Main() calling vec.top is fine,why?
Now I am trying to implement the generic version as below:
This time the running result is not correct;and if I change Stack<int> to Stack<double>,the output will be correct.This is quite wierd.
Regards,
Sam
Code: Select all
import "ecere"
#include <assert.h>
#include <stdlib.h>
#include <math.h>
#define maxStack 16
class Stack
{
private:
int arr[maxStack];
int top;
public:
void push(int elem)
{
assert(!isFull());
arr[top]=elem;
++top;
}
int pop()
{
assert(!isEmpty()) ;
--top;
return arr[top];
}
Stack()
{
top=0;
}
bool isFull()
{
return top==maxStack;
}
bool isEmpty()
{
return top==0;
}
};
class App:Application
{
void Main()
{
Stack vec{};
while(!vec.isFull())
vec.push(rand());
printf("top()=%d\n",vec.top);
while(!vec.isEmpty())
{
printf("pop first=%d\n",vec.pop());
}
system("pause");
}
}
the private field top should not be accessed outside,am I right?But in the Main() calling vec.top is fine,why?
Now I am trying to implement the generic version as below:
Code: Select all
import "ecere"
#include <assert.h>
#define maxStack 16
class Stack <class T>
{
private:
T arr[maxStack];
int top;
public:
void push(T elem)
{
assert(!isFull());
arr[top]=elem;
++top;
}
T pop()
{
assert(!isEmpty()) ;
--top;
return arr[top];
}
Stack()
{
top=0;
}
bool isFull()
{
return top==maxStack;
}
bool isEmpty()
{
return top==0;
}
};
class App:Application
{
void Main()
{
Stack<int> vec{};
vec.push(1);
vec.push(2);
vec.push(3);
printf("top()=%d\n",vec.top);
while(!vec.isEmpty())
{
printf("pop first=%d\n",vec.pop());
}
system("pause");
}
}
Regards,
Sam
Re: Can I define my own template functions?
Hi Sam,
As I mentioned earlier, these templates are still somewhat shaky grounds.
I've found that if you modify your pop function to return like this:
The problem goes away (Works fine for both int and double -- as long as you use %f for double of course). If you wish you could file a Mantis issue for this.
Also be warned that T arr[maxStack] gets compiled to a fixed-sized (as if T took 8 bytes).
On another note, all the predefined container classes inherit from Container, so you could make your Stack class inherit from it as well to test those features. Or it could inherit from Array
Regarding top being accessible from App::Main(), please read the chapter on Encapsulation and access control in eC, starting on page 85 in the Tao. It differs significantly from the C++ ideas:
- static means accessible only within the current .ec source file
- private means accessible only within this shared library (.dll/.so)
- public means accessible by all
In no case will a member of any class defined within a .ec file not be accessible within the same .ec file -- I would find this a terrible annoyance. The idea is that classes should be organized in source files according to functionality, e.g. the implementation for a major class and other related classes could go together in one source file, thus making member access between them easy (In C++ terms, you could think of it as all classes within a source files being friends). Things that should not be accessible by other unrelated classes can be made static (though there are currently limitations to the usage of static), and things that should only be invisible to the outside world would be made private (and only be seen within the shared library module source files).
Regards,
Jerome
As I mentioned earlier, these templates are still somewhat shaky grounds.
I've found that if you modify your pop function to return like this:
Code: Select all
return ((T*)arr)[top];
Also be warned that T arr[maxStack] gets compiled to a fixed-sized (as if T took 8 bytes).
On another note, all the predefined container classes inherit from Container, so you could make your Stack class inherit from it as well to test those features. Or it could inherit from Array
Regarding top being accessible from App::Main(), please read the chapter on Encapsulation and access control in eC, starting on page 85 in the Tao. It differs significantly from the C++ ideas:
- static means accessible only within the current .ec source file
- private means accessible only within this shared library (.dll/.so)
- public means accessible by all
In no case will a member of any class defined within a .ec file not be accessible within the same .ec file -- I would find this a terrible annoyance. The idea is that classes should be organized in source files according to functionality, e.g. the implementation for a major class and other related classes could go together in one source file, thus making member access between them easy (In C++ terms, you could think of it as all classes within a source files being friends). Things that should not be accessible by other unrelated classes can be made static (though there are currently limitations to the usage of static), and things that should only be invisible to the outside world would be made private (and only be seen within the shared library module source files).
Regards,
Jerome
Re: Can I define my own template functions?
Hi Jerome,
Thanks a lot.For the private scope,noted.
For the generic Stack function,double and int are fine after tested.But not for char* (String):
Output:
This is the 9 line
This is the 9 line
This is the 9 line
...
Don't know whether I missed something very obvious.
Regards,
Sam
Thanks a lot.For the private scope,noted.
For the generic Stack function,double and int are fine after tested.But not for char* (String):
Code: Select all
...
Stack<String> strVec{};
String str;
int i;
for(i=0;i<10;i++)
{
sprintf(str,"This is the %d line",i);
strVec.push(str);
}
while(!strVec.isEmpty())
printf("pop strVec==>%s\n",strVec.pop());
This is the 9 line
This is the 9 line
This is the 9 line
...
Don't know whether I missed something very obvious.
Regards,
Sam
Re: Can I define my own template functions?
Hi Sam,
You missed 2 things here
First, the 'String' class at the moment works pretty much like a typedef to 'char *' (so It's essentially a C string)
This means that you need to think of it as such, and so here you're doing a sprintf into an uninitialized pointer.
Additionally, when you push a String onto your class, no special code generates a copy for each added string, so you're essentially pushing the same string (And modifying it will modify all other strings in the stack, since they're the same -- that's why you get the same line printed 10 times).
The following will work:
PrintString works just like Print() (There's also PrintLnString()), but instead of outputting to stdout, it allocates and returns the resulting string.
Regards,
Jerome
You missed 2 things here
First, the 'String' class at the moment works pretty much like a typedef to 'char *' (so It's essentially a C string)
This means that you need to think of it as such, and so here you're doing a sprintf into an uninitialized pointer.
Additionally, when you push a String onto your class, no special code generates a copy for each added string, so you're essentially pushing the same string (And modifying it will modify all other strings in the stack, since they're the same -- that's why you get the same line printed 10 times).
The following will work:
Code: Select all
Stack<String> strVec{};
int i;
for(i=0;i<10;i++)
{
strVec.push(PrintString("This is the ", i, " line"));
}
while(!strVec.isEmpty())
{
String s = (String)strVec.pop();
printf("pop strVec==>%s\n",s);
delete s;
}
Regards,
Jerome
Re: Can I define my own template functions?
Thanks a lot.Got the point(maybe not yet ^_^)
As a practice I want to make it by pure char array instead of PrintString(),but still it prints This is line 9 ten times.Even if I use another char str[255] and then do strcpy from result to str ,it still does not work.Why?
Regards,
Sam
Code: Select all
for(i=0;i<10;i++)
{
char result[255];
sprintf(result,"This is line %d",i);
strVec.push(result);
}
Regards,
Sam
Re: Can I define my own template functions?
Hi Sam,
You still need to have one allocated string per thing added to the stack...
This would work:
-Jerome
You still need to have one allocated string per thing added to the stack...
This would work:
Code: Select all
for(i=0;i<10;i++)
{
char result[255];
sprintf(result,"This is line %d",i);
strVec.push(CopyString(result));
}
Re: Can I define my own template functions?
You have to realize the life of a char array is limited to its scope (the compound { } brackets around it), so as soon as you're outside of the for loop iteration, it's gone.
Re: Can I define my own template functions?
Appreciated.
Btw,does CopyString do the same as strdup?
The more I study deep into eC,the more I love.Keeping its features within a deeply thoughtful range other than bloated as c++ makes eC more beautiful and powerful.
Btw,does CopyString do the same as strdup?
The more I study deep into eC,the more I love.Keeping its features within a deeply thoughtful range other than bloated as c++ makes eC more beautiful and powerful.