Monday, July 16, 2007
item 46 and item 47 ...dont really understand them
Tuesday, July 3, 2007
Factor parameter independent code out of templates
In non template code repliation is explicit, you can see that there's duplication between two functions or two classes. In template code replication is imlicit there;s only one copy of the template source code ..but replication happens when the template is instantiated multiple times.
Non type parameters and type parameters both can cause bloat.
There are a lot of factors involved in determining performance improvement like size of binary, locaity improvement, cimpiler optimizations, program's working set size.
The best way to find the effect is to just try it out on representative data sets and the platforms concerned.
Things to remember:
Templates generate multiple classes and multiple functions, so any template code not dependent on a template parameter causes bloat.
Bloat due to non type template parameters can often be eliminated by replacing tempalte parameters with function parameters ro class data members.
Bloat due to type aparameters can be reduced by sharing implementations for instantiation types with identical binary representations.
Monday, July 2, 2007
use member function templates t o accept all compatible types
real pointers support implicit conversions very well. (eg. derived->base, non const -> const)
iterators into stl containers are almost always smart pointers
class top
class middle : public top
class bottom : public middle
now in templates to ge tmiddle to convert to top we need
template <typename t?
class smartptr {
public:
explicit smartptr(t* realptr);
};
smartptr<top> pt1 = smarptr<middle>(new middle); to get this to compile we will need the corresponding constructor in the smartptr definition, since compilers dont assume any relation between smartpttr<top> and smartptr<middle> classes.
easiest way to get around is ( but bad)
template typename<t>
class smartptr{
public:
template <typename u>
smartptr(const smartptr<U> & other);,....
}
but this allows converting top object to middle object also.
such functions are called generalized copy constructors. its not declared explicit sive type conversions among built in pointer types.
so what we do is simply use member initialization list to initialize parameters with true ptrs of the other object . then it can compile only if each naked ptr can be converted to the type to which we are trying to convert the object.
there are more things here that i dont really understand ...
c+= states that if a copy constructor is needed and you dont declare one it will be generated for you ( so if you only have a generalized template than it wont be used by the compiler )
things to remember:
use member function templates to generate functions that accept al lcompatible types
if you declare member templates for generalized copy construction or generalized assignemnt you will still need to declare normal copy constructor and copy assignment operator also.
Sunday, July 1, 2007
know how to access names in templatized base classes
so basically in templates inheritance stops working.
three ways around this :
prefix calls to base class functions with this-> ( why does it work ?...as in how does it work underneath?)
use a using declaration e,g,
template
class logginmsgsender:public msgsender
public:
using msgsender
void sendclearmsg(msginfo& info)
{
sendClear(info);
}
};
or you can exactly specify the function being called in the base class as in
msgsendder
its least desirable because if senclear is virtual than the effect of virtual is lost
note that all of these solutions basically promise the compiler that the definition of the function will be available, and so when it sees a call to senclearmsg and if it found that the expected function is not available, then it will still give you a compiler error.
so basically the availablity of a function call or something else is checked only when its usage is encountered.....so if i declare a class that doesnt define sendclear function but neither uses sendclearmsg function than it will compile and execute without error ? is that right ?
things to remember:
in derived class templates refer to names in base class templates via a this->prefix via using declarations or via an explicit base class qualification.
understand the two mieanings of typename
when a dependent name is nested inside a class it is a nested dependent name.
nested dependent type name i.e. a nested dependent name that refers to a type
non dependent names --opposite of this
if the parser encounters a nested dependent name in a template it assumes that the name is not a type unless you tell it otherwise. by default nested dependent typenames are not types.
so u say: typename c::const_iterator iter(container.begin());
the simple general rule is that anytime you refer to a nested dependent typename in a template you must immediately precede it by the word typename
exception to above rule is that typename must not precede nested dependent type names in a list of base classes or as a base class identifier in am ember initialization list.
typedef typename std::iterator_traits
value_type temp(*iter)
enforcement of the typename rule varies from compiler to compiler.
things to remember:
when declaring template parameters class and typename are interchangeable.
use typenames to idnetify nested dependent type names except in base class lists or as a base class identifier in a member initialization list
understand implicit interfaces and compile time polymorphism
in template programming implicit interface and compile time polymorphism move to the fore.
basically the point is that the interface that a template class must support is defined by the operations and function calls that has been made on the object instantiated from it.
so if their is a template class and two different fns are involed on two different instantiations then do both types need definition of that kind of object ?a1.f00() , a2.foo1() ---- does this mean a1.foo1() also has to be defined ?? ..not sure if this quesiton makes sense
things to remember:
both classes and templates support interfaces and polymorphism
for classes interfaces are explicit and centered on function signatures, polymorphism occurs at runtime through virtual functions
for template parameters interfaces are implicit and based on valid expressions polymorphism occurs during compilation through template instantiation, and function overloading resolution.
use multiple inheritance judiciously
class borrowableitem{
public:
void checkout();
};
class electronicgadget{
private :
bool checkout() const;
}
class mp3player: public borrowable, public electronicgadget { }
mp3player mp3
mp3.checkout() is ambigous because to find hte appropriate function to call c++ doesnt worry about its access level.
deadly diamond
whenever you have diamond think whether their should be only one copy of the base class or it should be one per path.
if you only want one copy of the base class then make the derived classes have a virtual inheritance. e.g.
class file {}
class inputfile : virtual public file {...}
class outputfile: virtual public file {...}
class iofile: public inputfile, public outputfile {,,}
what structure of outputfile was just normal inheritance ?
what if outputfile has virtual private inheritance ?
STL has a similar class hierarchy in basic_ios, basic_istream , basic_ostream and they are all templates
the reponsiblity for initializing a virtual base class is born my the most derived class....that means a derived class has to be aware of a virtual base, independent of how far down it is
try not to use virtual inheritance. if you must try not to put data members in there.
inheritance is necessary if virtual functions are to be redefined
things to remember:
multiple inheritance is more complex than single inheritance., it can lead to new ambiguity issues and to the need for virtual inheritance.
virtual inheritance imposes costs in size speed and complexity of initialization and assignment. its most practical when virtual base classes have no data.
multiple inheritance does have legitimate uses. one scenario involves combining publid inheritance from an interface class with private inheritance from a class that helps the implementation.