1

I'm pretty rusty with my c++. This is at the beginning of the class declarations in the header file for a bag class which uses an array to store data items. It's supposed to function as, you guessed it, a bag. I get the first line, but after that I don't quite understand what's going on. This seems fairly common so I think there's enough information here to get help.

class bag
{
public:
    // TYPEDEFS and MEMBER CONSTANTS
    typedef int value_type;
    typedef std::size_t size_type;
    static const size_type DEFAULT_CAPACITY = 30;  
nvoigt
  • 75,013
  • 26
  • 93
  • 142
Beezly
  • 49
  • 7
  • possible duplicate of [What is the use of typedef?](http://stackoverflow.com/questions/2566027/what-is-the-use-of-typedef) – Conner Feb 11 '14 at 06:33
  • Maybe a duplicate of another post but not that. Those second two statements are confusing. I didn't see any help with them. – Beezly Feb 11 '14 at 06:36
  • How come you understand the first typedef, but not the second one? It's the same thing! Or do you get confused by the `std::` namespace specifier? – Ferdinand Beyer Feb 11 '14 at 06:37

3 Answers3

5
typedef int value_type;

This line defines that the type bag contains another type called "value_type" that is the same as an int.

typedef std::size_t size_type;

This line defines that the type bag contains another type called "size_type" that is the same as an std::size_t.

static const size_type DEFAULT_CAPACITY = 30; 

This line defines a constant of type "size_type" (look at the line above to check what it is) that is called DEFAULT_CAPACITY with the value of 30.

That's basic C++ and I don't really know how to explain it better than to spell out the syntax.

nvoigt
  • 75,013
  • 26
  • 93
  • 142
  • 2
    One might add that the `typedef int value_type` has *probably* been done to have a type for the items the bag can hold, so if you suddenly want your bags to hold doubles, you can change that line to `typedef double value_type` instead of searching your source code for `int` variables and decide for each of them whether or not they should be changed to doubles as well. Of course, a more generic way to achieve this is templating. – Guntram Blohm Feb 11 '14 at 06:39
  • Ok then I suppose the big question is what is "an std::size_t"? – Beezly Feb 11 '14 at 06:47
  • 1
    @Beezly It's part of the standard library, an implementation defined unsigned int type. – nvoigt Feb 11 '14 at 06:50
  • @nvoigt It all makes sense now, thanks. I was actually looking up size_t right as you commented. I don't think this a duplicate post, but, well, what should I do? delete it? – Beezly Feb 11 '14 at 07:03
  • 2
    @Beezly, if it's a duplicate, it will be closed as duplicate. It's still somewhat useful as people who are looking things up might hit your question first and if it's closed as duplicate they will be guided to the other question. – nvoigt Feb 11 '14 at 07:25
2

The trick I've found with typedefs is to first ignore the typedef keyword and look at the other bits; so

int value_type;

would declare a variable called value_type of type int. Add the typedef keyword, and it's exactly the same, but rather than declaring a new variable, you're declaring a new type that's an int.

I find this helpful in more complex cases like

typedef int (*Func)(float, double);

Remove typedef and you're declaring a function called *Func which takes two parameters and returns an int. Add the keyword back in, and you're declaring a function type with that signature.

EDIT:

From comments on other answers, it seems like it's not so much the typedef itself but std::size_t that's giving you bother.

std::size_t is itself the name of a standard library type, specifically, the type of the number returned by the built-in sizeof operator. It's always an unsigned integer, but the exact type depends on the compiler and the system you're using (and even particular compiler options).

How do you know that std::size_t is a type name, rather than a variable name? The short answer is that you often can't, you just have to judge by the name and the context (in fact, sometimes even the compiler doesn't even know whether a name refers to a type or whether it refers to a variable, so you have to tell it). In this case, the fact that it ends in _t is a good clue that it's a type (plus the fact it's used in a typedef!).

The std part refers to the std namespace. Namespaces are a C++ facility (also present in other languages, though not C) for avoiding name clashes. You can declare your own, and std is a special on reserved for the standard library.

The A::B thing is called the scope resolution operator, and it tells the compiler "look inside A for something named B", where A can be either class or a namespace.

Tristan Brindle
  • 16,281
  • 4
  • 39
  • 82
1

The basic syntax of a typedef is:

"typedef" <name of type> <name of alias for type>

The name of the alias is a single identifier. Everything between the typedef key word and that last identifier needs to be the name of a/the type for which you're creating an alias. Of course, for things like pointers and references, especially something like an alias for a pointer to a function returning int and taking a string and a long as parameters, the name of the alias is going to be buried somewhere in the middle of the declaration, just like it would be when/if you were declaring a variable of that type (in fact, syntactically, typedef was originally added to C as a "storage class" like auto or register, so it occupies exactly the same spot in a declaration as one of them would).

So, in typedef int value_type it's creating value_type as an alias for int.

Note, however, that in this case the value_type is nested inside of bag so the complete name of the name is bag::value_type. If you use other containers, you'll probably have a value_type for each. For example:

std::vector<unsigned> x;

In this case, the value_type will also being unsigned. value_type becomes more interesting with associative containers like std::map. For example, given a map like:

std::map<std::string, int> foo;

...the value_type will be std::pair<const std::string, int>.

These nested identifiers like value_type are used especially heavily in template code that might take containers of different types (or iterators to the contents of such containers), so the value_type for a particular container isn't known when the code is written. For example, if you wanted to add together all the items in a container, you could use the container's value_type for the type of the result, so when you add together a vector<int>, the result would be an int, but if you add together a list<string>, the result would be a string.

Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111