Named CTORs - symualting it by tempaltes?
Hello,
this post is a big long so I made 3 sections
1. problem
2. code + compilation errors
3. idea for c++0x - new c++ standard? how about that...
=== 1 ===================================================================
in some languages (like pascal, delphi) we can construct object using meany
functions with different names.
I would like to have something like this in C++.
To to do like:
class cRec {
cRec() { } // ctor
constructor CreateSimmilarTo(cRec &org) {}
constructor CreateRecordDeleting(cRec &org) {}
constructor CreateRecordUpdating(cRec &org, int timestamp) {}
};
and so on.
in c++ I can do it, as long if all CTORs differ by arguments, which is not
the case in c++/pascal like code above.
Of course I can work around it in meany ways, but no sollution is too nice.
class cRec {
cRec() { } // ctor
cRec(int action, cRec &org, int timestamp=0) {
if (action==1) { } // CreateSimmilarTo
else if (action==2) { } // CreateRecordDeleting
else if (action==3) { } // CreateRecordUpdating
}
};
it is not too nice, as it will not detect compile-time invalide combination
of action and following arguments like new cRec(1,123) or cRec(3);
=== 2 ===================================================================
Therfore, my idea was to simulate it a bit by using templates, something
like:
cRec::cRec<0>(){}
cRec::cRec<1>(cRec &org){}
cRec::cRec<2>(cRec &org){}
cRec::cRec<3>(cRec &org, int timestamp){}
and usign it like:
cRec * x = new cRec<0>();
cRec * x = new cRec<2>(y);
cRec * x = new cRec<3>(y,time());
is that possible?
I tried something like:
--- code ---------------------------------------------------
template <int i> void bar() { } // this all works, as excercise
template <> void bar<0>() { } // ok
template <> void bar<1>() { } // ok
template <> void bar<2>() { } // ok
class cRec { // a record
template <int x> cRec(const char *a) {}
template <> cRec<0>(const char *a) {}
template <> cRec<1>(const char *a) {}
};
int main() {}
--- code ---------------------------------------------------
x.cpp:8: error: explicit specialization in non-namespace scope 'class cRec'
x.cpp:8: error: 'cRec' is not a template
x.cpp:8: error: expected unqualified-id before 'const'
x.cpp:8: error: expected `)' before 'const'
x.cpp:9: error: explicit specialization in non-namespace scope 'class cRec'
x.cpp:9: error: 'cRec' is not a template
x.cpp:9: error: expected unqualified-id before 'const'
x.cpp:9: error: expected `)' before 'const'
=== 3 ===================================================================
Perhaps it would be a nice thing to have in C++ - name constructors?
It could reuse the keyword "new" to indicate that given function can be
called as constructor. It would change ABI / format of .o objects probably
to contain the additional information.
example of using would be:
cRec {
cRec() { } // normal, default ctor
cRec(int a) { } // normal ctor
cRec(int a, int b) { } // normal ctor overload
cRec(int a, std::vector<int> x) { } // normal ctor overload
// named constructors:
new FromTemplate(int x){} // use database record number X as template
new FromTemplate(const cRec &org){} // use record as template
// create from template, but ask user to customize it
new SimmilarTo(int x){}
new SimmilarTo(const cRec &org){}
// create from template, but use it as a record to delete existing one
new Deleting(int x){}
new Deleting(const cRec &org){}
// create from template, but use it as a record to supersede existing one
new Updating(int x){}
new Updating(const cRec &org){}
};
Of course it all could be done more manually, like by having empty default
constructor, and then calling some methods to finish creation, like
cRec *r = new cRec(100);
r->SetRole_Deleting();
but for more complicated cases it is far more elegant solution, in example
when immediatelly passing it to function
SendToDatabase( new cRec(100) .... )
have to be splited into:
cRec *r = new cRec(100);
r->SetRole_Deleting();
SendToDatabase(r);
In my extended c++ idea, the syntax would be elegant:
SendToDatabase(new cRec::Deleting(100));
Nowdays this also can be done, by a static method cRec::Deleting that would
be a factory function, creating and returning cRec*, but this is not too
elegant IMHO - what if we want to use something else then a new, like
placement new?
Any suggestions or opinions are wellcommed :)
--
RafaV Maj