Alex Jenter
Alex Jenter

Reputation: 4432

What's the point of "typedef sometype sometype"?

Lately I've run into the following construction in the code:

typedef sometype sometype;

Pay attention please that "sometype" stands for absolutely the same type without any additions like "struct" etc.

I wonder what it can be useful for?

UPD: This works only for user defined types.

UPD2: The actual code was in a template context like this:

template <class T>
struct E
{
   typedef T T;
   ...
}

Upvotes: 6

Views: 1082

Answers (6)

Kaz Dragon
Kaz Dragon

Reputation: 6809

How about to make Template parameters visible to outside entities?

template <class Foo>
struct Bar
{
    typedef Foo Foo;
};

int main()
{
    Bar<int>::Foo foo = 4;
}

Note: this is actually not allowed in standard C++, but is specific to MSVC. See comments.

Upvotes: 7

Notinlist
Notinlist

Reputation: 16640

New idea! Certain clubs of programming like extensive usage of typedefs...

zoo/animals/types.h:

namespace zoo
{
    namespace animals
    {
        typedef size_t Count;
        // ...
    } // namespace animals
} // namespace zoo

zoo/animals/zebra.h:

#include "zoo/animals/types.h"

namespace zoo
{
    namespace animals
    {
        class Zebra {
        public:
            typedef Count Count;
            Count getLegCount() const;
            // ...
        }; // class Zebra
    } // namespace animals
} // namespace zoo

main.cpp:

#include "zoo/animals/zebra.h"

int main()
{
    typedef zoo::animals::Zebra Zebra;
    Zebra z;
    Zebra::Count n = z.getLegCount();
    // Not as zoo::animals::Count
    // No using namespace zoo::animals required,
    // we are using just one item from there, the Zebra.
    // Definition of Zebra::Count may change, your usage remains robust.
    return 0;
}

I just have a similar situation at my workplace. The translation of it may be a little bit silly, but I wanted to present it in a hurry.

Upvotes: 0

Matthieu M.
Matthieu M.

Reputation: 299800

As it as already been mentioned, it works especially well within a template:

template <class Foo>
struct Bar
{
  typedef Foo Foo;
};

But it can also be combined with template specialization:

template <class Foo>
struct Bar<Foo*>
{
  typedef Foo Foo;
};

Now, I can do:

Bar<int>::Foo i = 0;
Bar<int*>::Foo j = i;

Bar thus effectively behaves as a kind of type wrapper, which may be important for its interface (if there is a bool equals(Foo i) const for example).

Usually the name elected has some meaning value_type for example...

Upvotes: 1

Konrad Rudolph
Konrad Rudolph

Reputation: 545588

Given your additional information about templates, we can now answer.

The use-case is when you want to specialize on the type of a template. One typical example is the following:

template <typename T>
struct nonconst {
    typedef T t;
};

template <typename T>
struct nonconst<T const> {
    typedef T t;
};

This effectively allows you to remove the const qualifier from any type:

nonconst<int>::t x;
nonconst<int const>::t y;
assert(typeid(x) == typeid(int));
assert(typeid(y) == typeid(int));

There are many similar use-cases, e.g. to add (or remove) the pointer qualifier from a type, provide defaults and specializations for certain types, etc.

However, notice the different casing of the type names! Equal types in typedef T T are illegal C++.[I stand corrected: §7.1.3.2] Furthermore, the de-fact naming standard (cemented by its use in Boost libraries) is to call the type name alias type, e.g.:

typedef T type;

Upvotes: 7

Notinlist
Notinlist

Reputation: 16640

I have a theory. It could be a result of some refactorings. For example a templated type become not templated.

typedef SomeCleverTemplate<Rocket> SuperThing;

Then they deleted the template, beacuse there were no other usage of it in the code, and for just to be safe they replaced every SomeCleverTemplate<Rocket> to SuperThing.

typedef SuperThing SuperThing;

Does it make sense in the real context?

Upvotes: 6

Douglas Leeder
Douglas Leeder

Reputation: 53310

In C++, you can put a typedef in a namespace or class, and then refer to it relative to that namespace or class, which can be useful if the real type might change in the future.

e.g.

class IntHolder
{
    public:
        typedef int int;
        IntHolder::int i;
};
...
IntHolder foo;
IntHolder::int i = foo.i;

(NB: I haven't checked that's quite the right syntax - but hopefully you get the idea)

If at some future point you actually want to hold long in IntHolder you only need to change the IntHolder code.

Now, normally you name the type differently, but maybe you can do as above?

Upvotes: 6

Related Questions