Petr Skocik
Petr Skocik

Reputation: 60107

Are public, in-class typedefs necessary in C++1y?

I've noticed std:: containers tend to have public, in-class type aliases (typedef/using). E.g., see Member Types at http://en.cppreference.com/w/cpp/container/vector.

How are they useful? Aren't they just a relic of times when C++ didn't have things like auto and decltype?

When implementing a custom container, should it have such typedefs? What do I lose if I fail to provide them?

Upvotes: 10

Views: 335

Answers (3)

Vlad from Moscow
Vlad from Moscow

Reputation: 311068

typedef(s) allow to separate implementations from interfaces.

Take into acount that early the C++ does not define auto as it is defined now and decltype was absent in the Standard.

But even now when you have auto and decltype sometimes it is better to specify explicitly the type of an object. Otherwise the code can be difficult to read or it can lead to errors.

Consider a simple example with type specifier auto

unsigned int x = 0;
long y = 0;

auto p = new auto( x + y );

Can you say what is the type of the pointer p?

Is expression *p of unsigned type or signed type?

The answer depends on used platform. The type of p can be either long * or unsigned long *.

A similar problem exists for standard containers. So the Standard introduces general type names like size_type that guarantees that this type is unsigned type but its width can vary among platform.

Also this allows to write generic code.

In my profile there is a reference to my article where I show a problem that is related that standard class std::bitset does not have generic type size_type. In this case if you need to substitute for example class std::vector<bool> to std::bitset you need to change the code everywhere where there was used either size_type or some explicit type like size_t.

Upvotes: 1

n. m. could be an AI
n. m. could be an AI

Reputation: 120031

If you want a standard-library-compatible container, you do have to supply the typedefs.

If you look at the documentation, e.g. at cppreference, you will see passages like this:

std::vector meets the requirements of Container, AllocatorAwareContainer, SequenceContainer, ContiguousContainer (for T other than bool) (since C++17) and ReversibleContainer.

If you look up Container or SequenceContainer or any other thing listed there, you will find a list of requirements, and the typedefs (or rather types—they don't have to be typedefs, though they often are) are among them.

So if you are building a Container in the standard sense of the term, you need to provide the typedefs (and of course satisfy all other requirements too).

C++11 could in theory loosen the requirements, but it didn't. Perhaps because

std::vector<int>::iterator

is a heck of a lot more readable than

decltype(std::declval<std::vector<int>>().begin())

Or perhaps for some other reason.

Upvotes: 7

David Haim
David Haim

Reputation: 26506

They are extremly usefull when dealing with meta-programing, period.

let's catch a container by reference once if it's a container of POD, and another time when it's not:

template <class T>
typename std::enable_if_t<std::is_pod<typename T::value_type>::value>
doSomething(T& container){
   //do something
}

template <class T>
typename std::enable_if_t<!std::is_pod<typename T::value_type>::value>
doSomething(T& container){
   //do something
}

I'm doing a lot of C++ for Windows, and since Windows API provide C structs, I use many techniques like these to diffrentiate between real C++ objects and WinApi structs.

Upvotes: 4

Related Questions