473,549 Members | 3,099 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Design Problem: "Smart Paramaters"

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<typena me 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<typena me 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<typena me T1, typename T2> class IfElse<true, T1, T2>
{ public: typedef T1 Type; };
template<typena me 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>::Ty pe 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.ne t.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++.m oderated. First time posters: Do this! ]

Jul 23 '05 #1
5 1638

Just add parameter, describing your class to TROM:

// T -- parameter type
// C -- our class type
template<class T,class C>
class TROM {
typedef typename IfElse< sizeof(T) <= 2 * sizeof(void *),
T,
T const&>::Type Type;
};

// and if type of parameter and type of our class is equal -- result is
// reference to class
template<typena me C>
class TROM<C,C>
{
public:
typedef C& Type;
};
Jul 23 '05 #2
Manvel Avetisian wrote:

Just add parameter, describing your class to TROM:

// T -- parameter type
// C -- our class type
template<class T,class C>
class TROM {
typedef typename IfElse< sizeof(T) <= 2 * sizeof(void *),
T,
T const&>::Type
Type;
};

// and if type of parameter and type of our class is equal -- result is
// reference to class
template<typena me C>
class TROM<C,C>
{
public:
typedef C& Type;
};


I don't think I described the problem very clearly last night, but this
reply did give me an idea for a work-around:

//
// TCROM: A workaround version of TROM for the special case of classes
// that have member functions that take instances of themselves as
// arguments: class X { ... void Foo(const X&); ...}; - call by referene,
// or class X { ... void Foo(X); ...}; - call by value. The problem with
// using TROM in this case: void Foo(typename TROM<X>::Type) is that at
// this point X is an "incomplete type", and the sizeof test above fails.
// The solution here is to pass TCROM a "storage type" T, which is a
complete
// type, and the class type C. If T is small then we "return" C, otherwise
// we return C const&.
//
template<typena me T, class C>
class TCROM
{
public:
typedef typename IfElse< sizeof(T) <= 2 * sizeof(void *),
C,
C const&>::Type Type;
};

Jul 23 '05 #3
Michael Olea wrote:
template<typena me T>
class TROM
{
public:
typedef typename IfElse< sizeof(T) <= 2 * sizeof(void *),
T,
T const&>::Type Type;
};
....
template<bool C, typename T1, typename T2> class IfElse;
template<typena me T1, typename T2> class IfElse<true, T1, T2>
{ public: typedef T1 Type; };
template<typena me T1, typename T2> class IfElse<false, T1, T2>
{ public: typedef T2 Type; };
....
template <typename T>
struct XTest
{
T x;
void DoOr(typename TROM<XTest<T> >::Type src) {x |= src.x;}
};

Any ideas?


Well, to take the size of "XTest<T>" (which "TROM<XTest <T> >" does), the
compiler has to instantiate the template "XTest<T>". Since instantiating
"XTest<T>" requires knowing (taking) the size of "XTest<T>" that's
infinite recursion - even if you rewrite it so that the "incomplete
type" error goes away (*a).
So you can only use the size of something else.

You could add an additional template parameter that tells the template
whether to use references to itself or copies or automatically decide
what to use. The first two versions can be implemented whithout
recursion, and the "auto" version could e.g. use the size of the "by
reference" version to decide what parameter-type to use.

---

*a: Which is possible by adding a "static const MySize" in "XTest<T>"
and make "TROM" use "T::MySize" instead of "sizeof(T)" . The code would
look like the following, which also makes the recursion pretty clear:

template<typena me T>
class TROM
{
public:
typedef typename IfElse< T::MySize <= 2 * sizeof(void *),
....
template <typename T, size_t S = sizeof(XTest<T> )>
struct XTest
{
static const MySize = S;
....

Here you could break the recursion by changing "size_t S =
sizeof(XTest<T> )" to "size_t S = sizeof(XTest<T, 0>)" which should have
the effect that the size of the "by-value" version is used to decide
which version to instantiate.

bye, Paul
Jul 23 '05 #4
On 6 Jun 2005 05:25:24 -0400, Michael Olea wrote:

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?

Since you're using TROM to select the function parameter type based on
the size of XTest<T> (which doesn't work because the size of XTest<T> is
unknown until the compiler comes to the end of the class definition
(during instantiation)) , you can instead pass the size of XTest<T>
member x to a NewTROM template

template<typena me T, size_t size>
class NewTROM
{
public:
typedef typename IfElse< size <= 2 * sizeof(void *),
T,
T const&>::Type Type;
};
void DoOr(typename TROM<XTest<T>,s izeof(x) >::Type src) {x |= src.x;}

because in this case, you know roughly how to calculate the size of
XTest<T>.
A couple of things to note : member functions of a class can have a
parameter type that is an incomplete class only if the class in question
is the class the function is a member of. Data members of a class
cannot have zero size even if their type is an empty class. You might
have to calculate an amount to allow for packing.

To overcome the unknown packing size allowance, you can create a "mirror
class" and use that to get the size i.e.
template <typename T>
struct XTestMirror
{
T x;
};

void DoOr(typename TROM<XTest<T>,s izeof(XTestMirr or<T>) >::Type src)
{x |= src.x;}

and hope that the mirror class has the same size as its counterpart.
With some effort, you may be able to automatically check that
sizeof(XTest<T> ) is the same as sizeof(XTestMir ror<T>) e.g. by using a
static data member of XTest<T> whose definition follows the XTest class
and whose initializer uses sizeof(XTest<T> ) == sizeof(XTestMir ror<T>) in
a way that causes a compile time error if not equal.

Graeme
Jul 23 '05 #5
Graeme Prentice wrote:
On 6 Jun 2005 05:25:24 -0400, Michael Olea wrote:

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?

Since you're using TROM to select the function parameter type based on
the size of XTest<T> (which doesn't work because the size of XTest<T> is
unknown until the compiler comes to the end of the class definition
(during instantiation)) , you can instead pass the size of XTest<T>
member x to a NewTROM template

template<typena me T, size_t size>
class NewTROM
{
public:
typedef typename IfElse< size <= 2 * sizeof(void *),
T,
T const&>::Type Type;
};
void DoOr(typename TROM<XTest<T>,s izeof(x) >::Type src) {x |= src.x;}

because in this case, you know roughly how to calculate the size of
XTest<T>.
A couple of things to note : member functions of a class can have a
parameter type that is an incomplete class only if the class in question
is the class the function is a member of. Data members of a class
cannot have zero size even if their type is an empty class. You might
have to calculate an amount to allow for packing.

To overcome the unknown packing size allowance, you can create a "mirror
class" and use that to get the size i.e.
template <typename T>
struct XTestMirror
{
T x;
};

void DoOr(typename TROM<XTest<T>,s izeof(XTestMirr or<T>) >::Type src)
{x |= src.x;}

and hope that the mirror class has the same size as its counterpart.
With some effort, you may be able to automatically check that
sizeof(XTest<T> ) is the same as sizeof(XTestMir ror<T>) e.g. by using a
static data member of XTest<T> whose definition follows the XTest class
and whose initializer uses sizeof(XTest<T> ) == sizeof(XTestMir ror<T>) in
a way that causes a compile time error if not equal.

Graeme


Thanks for the suggestions. NewTROM is similar to what I ended up doing:

template<typena me T, class C>
class TCROM
{
public:
typedef typename IfElse< sizeof(T) <= 2 * sizeof(void *),
C,
C const&>::Type Type;
};

The idea is that T is a "storage type" for C. I'll have to look more closely
at the "unknown packing" issues. I was assuming that given:

template<typena me A, typename B, typename C...>
struct Store
{
A anA;
B aB;
C aC;
...
};

template<typena me A, typename B, typename C...>
class X
{
Store<A,B,C...> myStorage;
};

that sizeof(Store<A, B,C...>) would equal sizeof(X<A,B,C. ..>)
but I suppose that need not be the case.

Thanks again for the comments.
- Michael

Jul 23 '05 #6

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
12244
by: Martin Goldman | last post by:
Hello all, I've been struggling for a few days with the question of how to convert "smart" (curly) quotes into straight quotes. I tried playing with the htmlentities() function, but all that is doing is changing the smart quotes into nonsense characters. I also searched the web for quite a while and was unsuccessful in finding a solution. ...
2
4262
by: Tim Hochberg | last post by:
During the recent, massive, painful Lisp-Python crossposting thread the evils of Python's whitespace based indentation were once again brought to light. Since Python' syntax is so incredibly brittle, and failure prone, it's amazing that we don't have more editor support for our feeble minds. To help reduce the severity of this crisis, I...
14
2656
by: David B. Held | last post by:
I wanted to post this proposal on c.l.c++.m, but my news server apparently does not support that group any more. I propose a new class of exception safety known as the "smart guarantee". Essentially, the smart guarantee promises to clean up resources whose ownership is passed into the function, for whatever defintion of "clean up" is most...
2
1868
by: Chris Lau | last post by:
What is the best way to compare two entries in a single table where the two fields are "almost" the same? For example, I would like to write a query that would compare the first two words in a "company" field. If they are the same, I would like to output them. For example, "20th Century" and "20th Century Fox" in the company field would...
11
7005
by: Ron | last post by:
Hello, I'm having an aggravating time getting the "html" spewed by Word 2003 to display correctly in a webpage. The situation here is that the people creating the documents only know Word, and aren't very computer savvy. I created a system where they can save their Word documents as "html" and upload them to a certain directory, and the...
2
2367
by: BobAchgill | last post by:
Is there a way to let the User click on a button on a web site and have that download and install my prepackaged compressed data directory and place it nicely under my existing VB .Net Form application on the User's computer? Maybe another way of asking the question is. Can I build a smart .msi "data" installer that will when clicked on as...
3
3208
by: red floyd | last post by:
I've got some code where somebody cut&pasted some comments from MS Word, and so these comments have "smart quotes" (in particular apostrophes) embedded. The apostrophe is character hex 0x92. 2.1 indicates that characters not in the source character set are converted to the universal character name that designates the character. So far,...
5
2882
by: Noozer | last post by:
I'm looking for a "smart folder" program to run on my Windows XP machine. I'm not having any luck finding it and think the logic behind the program is pretty simple, but I'm not sure how I'd implement this. I've done some VB6 programming and dabbled in VS.Net. Can someone share some pointers in how I could implement the following? ...
0
7520
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7718
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
7956
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
1
7470
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
0
7809
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6041
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
1
5368
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5088
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3498
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.