views:

187

answers:

4

Suppose I have something like this:

struct EmptyClass{};
template<typename T1, typename T2 = EmptyClass,
         typename T3 = EmptyClass, typename T4 = EmptyClass,
         ..., typename T20> class PoorMansTuple {
  T1 t1;
  T2 t2;
  ...
  T20 t20;
};

Now, I may waste up to 19bytes per PoorMansTuple.

Question is:

1) Is there a way to create a class of size 0?

2) Is there a way to conditionally define a varaible? Somethign like:

  T1 t1;
  if (T2 != EmptyClass) T2 t2; // pseudo code
  if (T3 != EmptyClass) T3 t3; // ...

Thanks!

The use of black magic macros is premitted.

I'm using g++ on MacOSX.

+1  A: 

1) No, because the instance of the class couldn't have a memory adress. It requires at least 1 byte to have an adress. -- that said, a class that don't have any instance and direct reference (used only at template generation for example) will have no size as it not be in the compiled program.

2) Not without macro...or maybe obscure template black arts that only boost.org ninjas can master. I've heard of the idea of compile-time "if" but it's not currently in any coming standard of the language AFAIK. That would have allowed it. As already said, maybe there is a trick to make it.

Klaim
+1  A: 
  1. A class has to have some size (at least one). See "What Is the Smallest Object Size Possible in C/C++?"
  2. AFAIK, no you can't.
paleozogt
+4  A: 

Partial specialization may be what you are looking for the first part of the question. This program

#include <string>
#include <iostream>

struct EmptyClass {};

template<typename T1, typename T2>
class Tuple
{
   T1 t1;
   T2 t2;
};

template<typename T1>
class Tuple <T1, EmptyClass>
{
   T1 t1;
};


int main (void)
{
    Tuple<std::string, std::string> two;
    Tuple<std::string, EmptyClass> one1;
    Tuple<std::string> one2;

    std::cout << "<string, string>: " << sizeof(two) << std::endl;
    std::cout << "<string, empty> : " << sizeof(one1) << std::endl;
    std::cout << "<string>        : " << sizeof(one2) << std::endl;

    return 0;
}

prints

<string, string>: 32
<string, empty> : 16
<string>        : 16
Lars
(+1) You can cut down the amount of code needed by deriving the 2-tuple from the 1-tuple - that way you only have to define `T2 t2;` in the 2-tuple. Generalizing that, you only need to define one member per (n+1)-tuple by deriving from the n-tuple.
Georg Fritzsche
+1  A: 

Check out boost::tuple and boost::compressed_pair. A class can't have a sizeof 0, but there is the concept of the "empty base class" optimization. Eh, I'm just going to link to one of my previous answers, it is pretty relevant here IMO: http://stackoverflow.com/questions/97948/what-is-stdpair/573457#573457

Logan Capaldo