Ron
Ron

Reputation: 223

Advantages of an empty class in C++

What could be the possible advantages/uses of having an empty class?

P.S: This question might sound trivial to some of you but it is just for learning purpose and has no practical significance. FYI googling didn't help.

Upvotes: 22

Views: 27273

Answers (10)

dyomas
dyomas

Reputation: 720

For the sake of typeid

Suppose we have comparable interface Id. We need fill some container with unique instances of this interface. How to guarantee the uniqueness of Id instances produced by independent software parts? «Independent parts» means some different dynamic libraries, compiled by different programmers from different locations

One of decisions is to compare typeid of some type first. If typeid matches, convert and compare other implementation specific properties. C++ language guarantees uniqueness of any type within process memory. Which type should be used for this purpose? Any type with minimum resource consumption — empty one

Upvotes: 0

Nish Sinha
Nish Sinha

Reputation: 11

The answer by MartinStettner is fine though just to highlight an important point here: The concept of iterator tags or for that matter any tags in C++, is not strictly dependent on empty classes. The C++ tags, if stl writers would have wanted to, could well have been non-empty classes; that should work but then it won't add any additional value; at least for compile time acrobatics that it is usually reserved for.

Upvotes: 0

MartinStettner
MartinStettner

Reputation: 29174

One use would be in template (meta-)programming: for instance, iterator tags are implemented as empty classes. The only purpose here is to pass around information at compilation time so you can check, if an iterator passed to e.g. a template function meets specific requirements.

EXAMPLE:

This is really simplified, just to ge an idea. Here the purpose of the tag class is to decide, which implementation of an algorithm to use:

class forward_iterator_tag {};
class random_access_iterator_tag {};

class MySimpleForwardIterator {
public:
  typedef typename forward_iterator_tag tag;
  // ...
};

class MySimpleRandomIterator {
public:
  typedef typename random_access_iterator_tag tag;
  // ...
};

template<class iterator, class tag>
void myfunc_int(iterator it, tag t) {
  // general implementation of myfunc
}

template<class iterator>
void myfunc_int<iterator, forward_iterator_tag>(iterator it) {
  // Implementation for forward iterators
}

template<class iterator>
void myfunc_int<iterator, random_access_iterator_tag>(iterator it) {
  // Implementation for random access iterators
}

template<class iterator>
void myfunc(iterator it) {
  myfunc_int<iterator, typename iterator::tag>(it);
}

(I hope I got this right, it's been a while since I used this ...)

With this code, you can call myfunc on an arbitrary iterator, and let the compiler choose the correct implementation depending on the iterator type (i.e. tag).

Upvotes: 21

Dan
Dan

Reputation: 10393

As others have said, often an empty class (or struct) is used a placeholder, a differentiator, a token, etc.

For example, a lot of people are unaware that there are "nothrow" versions of operator new. The syntax to invoke nothrow new is:

p = new(std::nothrow) Bar;

and std::nothrow is defined simply as

struct nothrow_t {}; //defined in namespace std

Upvotes: 0

rve
rve

Reputation: 6055

The following can be used to have a boost::variant which can hold an (SQL) NULL value for example.

class Null { };

typedef boost::variant<Null, std::string, int> Value;

To make it more useful things like operator== and operator<< are handy. For example:

std::ostream& operator<<(std::ostream &lhs, const Null &rhs)
{
     lhs << "*NULL*";
     return lhs;
}

int main()
{
    Variant v("hello");
    std::cout << v << std::endl;
    v = Null();
    std::cout << v << std::endl;
    ...
}

Will give:

hello
*NULL*

Upvotes: 5

Stephane Rolland
Stephane Rolland

Reputation: 39916

In the STL, Standard Template Library of the C++, for example you have

template<class _Arg,
 class _Result>
struct unary_function
    { // base class for unary functions
 typedef _Arg argument_type;
 typedef _Result result_type;
    };

When defining a functor, you can inherit unary_function, and then you have the typedef defined automatically at your disposal.

Upvotes: 3

Stefano Leli
Stefano Leli

Reputation: 41

You can use it like a placeholder for checking purpose or as enabler to special functionality. For example in Java exist the "empty" interface Serializable used to specify if a class is serializable.

Upvotes: 2

SwDevMan81
SwDevMan81

Reputation: 50018

Here is an interesting link with answers to why its allowed. You might find this helpful to find situations where it might be useful.

Upvotes: 0

Javi Moya
Javi Moya

Reputation: 193

"empty" classes means classes which have no data members? They typically declare typedefs or member functions, and you can extend them with your own classes.

Upvotes: 0

KeithS
KeithS

Reputation: 71583

An empty class could be used as a "token" defining something unique; in certain patterns, you want an implementation-agnostic representation of a unique instance, which has no value to the developer other than its uniqueness. One example is Unit of Work; you may not care one bit about what's going on inside your performer, but you want to tell that performer that the tasks you're telling it to perform are part of an atomic set. An empty class representing the Unit of Work to the outside world may be perfect in this case; almost anything a Unit of Work object could store or do (encapsulating a DB transaction, exposing Commit/Rollback behaviors) would start tying you to a particular implementation, but an object reference is useful to provide a unique but copyable and passable reference to the atomic set of tasks.

Upvotes: 2

Related Questions