Here is a design problem I ran into this am - and I have cleaned the
bathroom,
scrubbed toilet sink and tub, windexed all glass, mopped the floor, and
vacuumed the house - no dice, the problem is still there. Maybe y'all have
some ideas?
Background
==========
The basic idea behind templates, of course, is that much code is independent
of the data types it works on: the basic operations of a doubly linked list,
for example, are identical whether it is a list of donuts or a list of cops.
Rather than duplicate the code for each list of items of type T we just
create a template for all lists independently of type by writing the list
in terms of a template argument: template<typename T> class DList, using T
wherever we normally would use a specific concrete data type - we let the
compiler duplicate the code. So far so good (ignoring "code bloat" issues
here).
But in truth we do not always want the code *entirely* independent of the
types it works on. A case in point is how we pass read-only paramaters to
functions (and to member functions). For "big" types (or types that are
expensive to construct) we want to pass a const reference, for other types
we would prefer to pass them by value - more efficient that way. So the
only difference, in this scenario, is how we declare function arguments.
A Solution?
===========
Vandervoode and Josuttis discuss, in C++ Templates: The Complete Guide, a
way out. My (very simple and nearly verbatim copied) implimentation is:
template<typename T>
class TROM
{
public:
typedef typename IfElse< sizeof(T) <= 2 * sizeof(void *),
T,
T const&>::Type Type;
};
Where IfElse is a "type function" that "returns" its second argument if the
first argument evaluates to true, its third argument otherwise:
template<bool C, typename T1, typename T2> class IfElse;
template<typename T1, typename T2> class IfElse<true, T1, T2>
{ public: typedef T1 Type; };
template<typename T1, typename T2> class IfElse<false, T1, T2>
{ public: typedef T2 Type; };
Now, I know TROM is naive in that a class or struct might be "small" yet
expensive to construct - that is not the issue here.
The Problem
===========
The prolem arises when some member functions of a class take instances of
the class itself as arguments:
struct XTest
{
unsigned int x;
void DoOr(typename TROM<XTest>::Type src) {x |= src.x;}
};
This fails to compile:
....
/usr/home/olea/binfosys/operations/base/include/binfosys/trom.h:44: `sizeof'
applied to incomplete type `XTest'
In this particular case I don't need TROM to tell me to pass XTest by value,
not by const reference, but if instead of "unsigned int" I use type T I do
need it:
template <typename T>
struct XTest
{
T x;
void DoOr(typename TROM<XTest<T> >::Type src) {x |= src.x;}
};
Any ideas?
Thanks for your consideration - Michael
ps:
tayfun.2wire.net.olea (118) g++ -v
Using built-in specs.
Configured with: FreeBSD/i386 system compiler
Thread model: posix
gcc version 3.2.2 [FreeBSD] 20030205 (release)
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]