What are the differences between using from typedef besides the fact that using works with templates? If only in this, then why it was impossible to add this support in typedef ?

    4 answers 4

    The using directive exists only in С++ , typedef is a legacy from pure C , there are no templates in it.

    Especially since they differ in nature. When using typedef we create a synonym for a type name, and using allows you to create a type synonym, or include an existing name in the current namespace.

    • those. Is it at the level of a fatal flaw? I always thought that typedef created a new typeid, but now I entered the following: ideone.com/KAW340 - arukasa
    • updated the answer, typedef sets a synonym for the name - Yuriy Orlov
    • one
      Namespaces are generally out of place here, because using as a typedef replacement is not the case that using is a declaration or a directive. - αλεχολυτ

    using allows you to write more beautiful code and allows you to get rid of the typedef legacy, which has def in its name, which may imply a definition that does not actually occur. using is a typedef replacement with some additions which typedef does not have. There is no point in using typedef in modern code.

    In more detail about what those who suggested this change in the standard think about, as well as using history, you can read on the English part of SO .

      I would say this - the main advantage of using over typedef is when working with templates. patterns. In particular, alias declarations can be template-based (and in this case they are called alias templates), while typedef are not. This gives C ++ 11 programmers a simple mechanism for expressing what in C ++ 98 could be expressed only by hacker methods, using typedef nested in a template struct . Consider, for example, the definition of a synonym for a linked list that uses a custom memory MyAlloc . In the case of alias templates, this is simple:

       // MyAllocList<T> является синонимом для std::list<T,MyAlloc<T>>: template<typename T> using MyAllocList = std::list<T, MyAlloc<T>>; MyAllocList<Widget> lw; // Клиентский код 

      In the case of typedef you have to go a long circular path:

       // MyAllocList<T>::type — синоним для std::list<T,MyAlloc<T>>: template<typename T> struct MyAllocList { typedef std::list<T, MyAlloc<T>> type; }; MyAllocList<Widget>::type lw; // Клиентский код 

      All the worse. If you want to use a typedef in a template to create a linked list that stores objects of the type specified by the template parameter, the name specified in typedef should be preceded by the typename keyword:

       template<typename T> class Widget { // Widget<T> содержит private: // MyAllocList<T>, typename MyAllocList<T>::type list; // как член-данные … }; 

      Here MyAllocList<T>::type refers to a type that depends on the template type parameter ( T ). Thus, MyAllocList<T>::type is a dependent type, and one of the C ++ rules requires that the names of dependent types are preceded by the keyword typename .
      If MyAllocList defined as an alias pattern, this requirement of using the typename keyword is removed (as is the cumbersome “ ::type ” suffix):

       template<typename T> using MyAllocList = std::list<T, MyAlloc<T>>; // Как и ранее template<typename T> class Widget { private: MyAllocList<T> list; // Ни typename, … // ни ::type }; 

      For you, MyAllocList<T> (i.e. using an alias pattern) may look like it is dependent on a template parameter T , like MyAllocList<T>::type (i.e., like using a nested typedef ), but you are not a compiler. When the compiler processes the Widget template and encounters using MyAllocList<T> (i.e. using an alias pattern), it knows that MyAllocList<T> is a type name, because MyAllocList is an alias pattern: it must be a type name. Thus, MyAllocList<T> is an independent type, and the typename specifier is neither required nor allowed.

      On the other hand, when the compiler sees MyAllocList<T>::type (that is, using nested typedef ) in the Widget template, it cannot know for sure that this construct names a type, since it can be the MyAllocList specialization with which it still not encountered and in which MyAllocList<T>::type refers to something other than type. It sounds silly, but don't blame the compilers for considering this possibility. In the end, it's people who write such code. For example, a certain lost soul is quite able to write the following:

       class Wine { … }; template<> // Специализация MyAllocList в class MyAllocList<Wine> { // которой T представляет собой Wine private: enum class WineType // См. в разделе 3.4 информацию об { White, Red, Rose }; // "enum class" WineType type; // В этом классе type представляет … // собой данные-член! }; 

      As you can see, MyAllocList<Wine>::type not a type. If the Widget instantiated with Wine , the MyAllocList<T>::type in the Widget template is a member data, not a type. Whether MyAllocList<T>::type refers to a type in a Widget template depends on what T , and therefore compilers require you to specify that it is a type preceding it with the keyword typename .

        Another convenience of using compared to typedef can be seen in the example of a pointer to a function (argument int, returns float):

         typedef float (*func_ptr)(int); using func_ptr = float (*)(int); 

        This is a matter of taste, but I prefer the second option.

        Subtracted from Scott Myers