简体   繁体   中英

Can somebody help me decipher the syntax in these typedef-ing lines?

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

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.

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 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM