Friday, April 15, 2016

Digest for comp.lang.c++@googlegroups.com - 7 updates in 2 topics

"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Apr 15 09:17AM +0200

Hi,
 
I want to use a template function to return a new (new-)instance of a class.
 
template < typename t_New >
t_New* Register_New(std::string vName, int vType){
c_idasection *nSec = NULL;
c_IDALabel *nLbl = NULL;
if(vType == 1){
nSec = new c_idasection(this, vName, 1);
return nSec;
} else if (vType == 3) {
nLbl = new c_IDALabel(this, vName, 1);
return nLbl;
}
return NULL;
}
 
c_IDALabel *lblInf = mXIDA.Register_New("lblInf", 3);
 
But I get the error:
/media/.../ida_login/c_xida.h:58: note: template argument
deduction/substitution failed:
 
I also tried:
template < typename t_New >
int Register_New(t_New *vNew, std::string vName, int vType){
c_idasection *nSec = NULL;
c_IDALabel *nLbl = NULL;
tdPair_RegObjA nPairA;
tdPair_RegObj nPair;
for(int i = 0; i < (int) this->mVecReg.size(); i++){
if(this->mVecReg[i].first == vName){
return 0;
}
}
if(vType == 1){
nSec = new c_idasection(this, vName, 1);
vNew = nSec;
} else if (vType == 3) {
nLbl = new c_IDALabel(this, vName, 1);
vNew = nLbl;
}
nPairA.first = vType;
nPairA.second = (void*) vNew;
nPair.first = vName;
nPair.second = nPairA;
this->mVecReg.push_back(nPair);
cout << "XIDA REGISTER OK >> TYPE == " << vType << " " << vName <<
endl ; cout.flush();
return 1;
}
 
But than I get the error:
'cannot convert from c_idasection to c_IDALAbel'
 
How can I make it work?
 
TIA
Heinz-Mario Frühbeis
Paavo Helde <myfirstname@osa.pri.ee>: Apr 15 11:28AM +0300

On 15.04.2016 10:17, Heinz-Mario Frühbeis wrote:
 
> But than I get the error:
> 'cannot convert from c_idasection to c_IDALAbel'
 
> How can I make it work?
 
It looks like you want to decide at run-time which class to create, i.e.
you want you decide at run-time which code to run. Alas, templates are a
compile-time feature, so it is impossible to use them in such a way
(with templates you need to know already at compile time which code you
want to run).
 
Not exactly sure what you want to achieve. One approach would be to
derive c_idasection and c_IDALabel from a common base class with virtual
interface. The function which does the runtime dispatch is an ordinary
function, not a template:
 
base* Register_New(std::string vName, int vType){
if(vType == 1) {
return new c_idasection(this, vName, 1);
} else if (vType == 3) {
return new c_IDALabel(this, vName, 1);
}
return NULL;
}
 
base* obj = Register_New("blabla", 1);
obj->SomeVirtualFunction();
 
Of course, using raw pointers is error prone, suggesting to use some
sort of smartpointers like std::unique_ptr or std::shared_ptr instead.
 
Another possibility is that you want to process things by some common
template function. In this case you still need non-template dispatch
function, which forwards to templates:
 
template<class T>
void Process(std::string vName) {
T obj(this, vName, 1);
obj.DoSomething();
// call some other templates, etc.
}
 
void Dispatch(std::string vName, int vType){
if(vType == 1) {
Process<c_idasection>(vName);
} else if (vType == 3) {
Process<c_IDALabel>(vName);
}
}
 
In this approach, there is no common base class or virtual functions
needed, but for example keeping the objects around for a later use would
be more cumbersome.
 
HTH
Paavo
"Heinz-Mario Frühbeis" <Div@Earlybite.individcore.de>: Apr 15 11:26AM +0200

Am 15.04.2016 um 10:28 schrieb Paavo Helde:
> On 15.04.2016 10:17, Heinz-Mario Frühbeis wrote:
>> Hi,
[...]
 
> In this approach, there is no common base class or virtual functions
> needed, but for example keeping the objects around for a later use would
> be more cumbersome.
 
Oh yes! You brought me on the right way!
 
My solution:
 
template < class T >
T* GetClass(std::string vName){
return new T(this, vName, 1);
}
 
template < typename t_New >
t_New* Register_New(std::string vName, int vType){
tdPair_RegObjA nPairA;
tdPair_RegObj nPair;
t_New *n_New = NULL;
for(int i = 0; i < (int) this->mVecReg.size(); i++){
if(this->mVecReg[i].first == vName){
return NULL;
}
}
n_New = GetClass <t_New> (vName);
nPairA.first = vType;
nPairA.second = (void*) n_New;
nPair.first = vName;
nPair.second = nPairA;
this->mVecReg.push_back(nPair);
cout << "XIDA REGISTER OK >> TYPE == " << vType << " " << vName <<
endl ; cout.flush();
return n_New;
}
 
c_IDAButton *lblInf = mXIDA.Register_New <c_IDAButton> ("lblInf", 3);
 
Thanks, sir; thanks a lot!
 
Regards
Heinz-Mario Frühbeis
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Apr 15 05:30PM +0200

On 15.04.2016 11:26, Heinz-Mario Frühbeis wrote:
> return n_New;
> }
 
> c_IDAButton *lblInf = mXIDA.Register_New <c_IDAButton> ("lblInf", 3);
 
This does not make sense to me.
 
The code above ensures that for a given type t_New only the first call
of `Register_New` with a given name will return a pointer to object,
where a type-erased (unusable) pointer to that object is saved in a
vector, and that all subsequent calls with that name should return NULL.
 
What's the POINT of this?
 
Anyway, regarding the use of Hungarian notation (the silly prefixes),
that was invented in order to support the help system in Microsoft's
"Programmers' Workbench" IDE in the middle to late 1980's, IIRC.
 
It's at least 26 years obsolete.
 
Although the [1] Wikipedia article on Hungarian notation sports some
statements (especially about BCPL) that look like uninformed guesses,
check out its opinion section.
 
 
Cheers,
 
- Alf
 
Notes:
[1] https://en.wikipedia.org/wiki/Hungarian_notation#Notable_opinions
Ian Collins <ian-news@hotmail.com>: Apr 16 08:17AM +1200

On 04/15/16 19:17, Heinz-Mario Frühbeis wrote:
 
> template < typename t_New >
> t_New* Register_New(std::string vName, int vType){
> c_idasection *nSec = NULL;
 
What the point of all those t_ v and c_ prefixes? They're just annoying
noise that gets in the way of reading the code.
 
--
Ian Collins
legalize+jeeves@mail.xmission.com (Richard): Apr 15 09:06PM

[Please do not mail me a copy of your followup]
 
Paavo Helde <myfirstname@osa.pri.ee> spake the secret code
>compile-time feature, so it is impossible to use them in such a way
>(with templates you need to know already at compile time which code you
>want to run).
 
Here's how I think of it:
 
Templates are static (compile-time) polymorphism.
 
Virtual methods and abstract base classes are dynamic (run-time)
polymorphism.
--
"The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline>
The Computer Graphics Museum <http://computergraphicsmuseum.org>
The Terminals Wiki <http://terminals.classiccmp.org>
Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com>
"Öö Tiib" <ootiib@hot.ee>: Apr 15 09:37AM -0700

On Thursday, 14 April 2016 19:46:50 UTC+3, Daniel wrote:
> thought out feature, ever by the standards of way back when. What I want to
> know when I call a method is whether it has side effects, and const is
> silent on that.
 
May be you search apples from apricot tree here. Main focus of C++
is on efficiency. Its raw features fit rarely exactly for something and are
even unsafe in clumsy hands. In typical code that we write we however
do not use most of the raw features directly. We do not write 'new' or
'delete' or use raw arrays and naked pointers because there are containers,
iterators and smart pointers.
 
Making a class with transitive immutability is simple using non-transitive
'const', while other way around it would be tricky. If you need a keyword
that indicates pureness of a function in C++ then quite close to it is
'constexpr'.
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: