tags:

views:

382

answers:

5

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;
   ...
}
+6  A: 

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?

Douglas Leeder
Honorary +1 for a decent use scenario. I can see this easily happening for types less built-in than `int`.
Chris Lutz
It doesn't seem to compile any more than all the other answers suggesting this (with GCC and Comeau). - If the class is supposed to have only one typedef, just use `typedef X type;`, so people wouldn't have to guess each time. I mean, `IntHolder::int` would turn out to be `long`? Why call it **int** then and not `IntHolder::type`?
UncleBens
I didn't try it - and I'm glad I didn't because I would have hit gcc refusing it - whereas the OP's compiler (VS) managed to compile the template version.
Douglas Leeder
As for the naming - it was a micro, non-compiled example. I hoped to get the idea across - and obviously the typedef had to be in that form to match the OP's question!
Douglas Leeder
+6  A: 

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?

Notinlist
Honorary +1 for "real context of too much automation". Sorry it's not a real +1, I'm out for the next 12 hours.
Chris Lutz
And why woudn't it work without a typedef?
Alex Jenter
It would. I think you can delete that line from the code.
Notinlist
+7  A: 

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: Please don't vote this up any more. It was a guess, and I've since tried it. It doesn't work.

Kaz Dragon
Then why not delete it?
anon
Pretty sure it works in some compilers, so if the OP has seen this code around, this might be why, so it's still a valid answer to his question.
jalf
@Niel: Because if I delete it, some other smart fellow will think of the same thing and post it again. Sometimes it's worth knowing what the wrong answer is.
Kaz Dragon
It works in MSVC, but it's illegal C++. See this question: http://stackoverflow.com/questions/486508/how-does-template-argument-shadowing-work-in-vs2005
Johannes Schaub - litb
Then we can all downvote the next smart guy? :)
UncleBens
Yes, I think this was the original intent of the code.
Alex Jenter
@Niel: Aaaaaand because sometimes a wrong answer is the right answer? *shrug*
Kaz Dragon
+7  A: 

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;
Konrad Rudolph
"Equal types in typedef T T are illegal " - this is incorrect. See 7.1.3.2 in the C++'03 Standard.
Alex Jenter
@Alex: I wasn’t aware of that. However, `g++` 4.4.2 (`-pedantic`) bails out when I use identical casing in the above code. So is this a compiler bug?
Konrad Rudolph
Sorry, I think the gotcha may be in the "non-class scope" remark. Comeau Online also doesn't compile this, but VC2008 does. I couldn't find the place in the standard that would explicitly disallow it (anyone?), so it may be implementation-defined.
Alex Jenter
@Alex, see http://stackoverflow.com/questions/486508/how-does-template-argument-shadowing-work-in-vs2005
Johannes Schaub - litb
Additionally, a member declaration is forbidden to introduce a name into a class scope that changes the result of lookup for a use of that name during completion of the class' scope. Having placed `typedef foo foo;` as a member declaration, however, does exactly that (it makes use of `foo`, but also declares a new name `foo`). See 3.3.6/1 bullet 2.
Johannes Schaub - litb
@Johannes: Thanks for the info! So this is just MSVC being non-conformant and someone taking advantage of it...
Alex Jenter
+1  A: 

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...

Matthieu M.