Edwin Vane | e4e7c24 | 2013-03-09 03:33:50 +0000 | [diff] [blame] | 1 | .. index:: Use-Auto Transform |
Edwin Vane | 3b9f08d | 2013-03-08 23:26:00 +0000 | [diff] [blame] | 2 | |
| 3 | ================== |
| 4 | Use-Auto Transform |
| 5 | ================== |
| 6 | |
| 7 | The Use-Auto Transform is responsible for using the ``auto`` type specifier for |
| 8 | variable declarations to *improve code readability and maintainability*. The |
Eric Christopher | 6cddedc | 2013-04-22 14:39:46 +0000 | [diff] [blame] | 9 | transform is enabled with the :option:`-use-auto` option of |
Chandler Carruth | d9063c4 | 2013-09-04 17:35:07 +0000 | [diff] [blame] | 10 | :program:`clang-modernize`. For example: |
Edwin Vane | 3b9f08d | 2013-03-08 23:26:00 +0000 | [diff] [blame] | 11 | |
| 12 | .. code-block:: c++ |
| 13 | |
| 14 | std::vector<int>::iterator I = my_container.begin(); |
| 15 | |
| 16 | // transforms to: |
| 17 | |
| 18 | auto I = my_container.begin(); |
| 19 | |
| 20 | The ``auto`` type specifier will only be introduced in situations where the |
| 21 | variable type matches the type of the initializer expression. In other words |
| 22 | ``auto`` should deduce the same type that was originally spelled in the source. |
| 23 | However, not every situation should be transformed: |
| 24 | |
| 25 | .. code-block:: c++ |
| 26 | |
| 27 | int val = 42; |
| 28 | InfoStruct &I = SomeObject.getInfo(); |
| 29 | |
| 30 | // Should not become: |
| 31 | |
| 32 | auto val = 42; |
| 33 | auto &I = SomeObject.getInfo(); |
| 34 | |
| 35 | In this example using ``auto`` for builtins doesn't improve readability. In |
| 36 | other situations it makes the code less self-documenting impairing readability |
| 37 | and maintainability. As a result, ``auto`` is used only introduced in specific |
| 38 | situations described below. |
| 39 | |
| 40 | Iterators |
| 41 | ========= |
| 42 | |
| 43 | Iterator type specifiers tend to be long and used frequently, especially in |
| 44 | loop constructs. Since the functions generating iterators have a common format, |
| 45 | the type specifier can be replaced without obscuring the meaning of code while |
| 46 | improving readability and maintainability. |
| 47 | |
| 48 | .. code-block:: c++ |
| 49 | |
| 50 | for (std::vector<int>::iterator I = my_container.begin(), |
| 51 | E = my_container.end(); |
| 52 | I != E; ++I) { |
| 53 | } |
| 54 | |
| 55 | // becomes |
| 56 | |
| 57 | for (auto I = my_container.begin(), E = my_container.end(); I != E; ++I) { |
| 58 | } |
| 59 | |
| 60 | The transform will only replace iterator type-specifiers when all of the |
| 61 | following conditions are satisfied: |
| 62 | * The iterator is for one of the standard container in ``std`` namespace: |
| 63 | |
| 64 | * ``array`` |
| 65 | |
| 66 | * ``deque`` |
| 67 | |
| 68 | * ``forward_list`` |
| 69 | |
| 70 | * ``list`` |
| 71 | |
| 72 | * ``vector`` |
| 73 | |
| 74 | * ``map`` |
| 75 | |
| 76 | * ``multimap`` |
| 77 | |
| 78 | * ``set`` |
| 79 | |
| 80 | * ``multiset`` |
| 81 | |
| 82 | * ``unordered_map`` |
| 83 | |
| 84 | * ``unordered_multimap`` |
| 85 | |
| 86 | * ``unordered_set`` |
| 87 | |
| 88 | * ``unordered_multiset`` |
| 89 | |
| 90 | * ``queue`` |
| 91 | |
| 92 | * ``priority_queue`` |
| 93 | |
| 94 | * ``stack`` |
| 95 | |
| 96 | * The iterator is one of the possible iterator types for standard containers: |
| 97 | |
| 98 | * ``iterator`` |
| 99 | |
| 100 | * ``reverse_iterator`` |
| 101 | |
| 102 | * ``const_iterator`` |
| 103 | |
| 104 | * ``const_reverse_iterator`` |
| 105 | |
| 106 | * In addition to using iterator types directly, typedefs or other ways of |
| 107 | referring to those types are also allowed. However, implementation-specific |
| 108 | types for which a type like ``std::vector<int>::iterator`` is itself a |
| 109 | typedef will not be transformed. Consider the following examples: |
| 110 | |
| 111 | .. code-block:: c++ |
| 112 | |
| 113 | // The following direct uses of iterator types will be transformed. |
| 114 | std::vector<int>::iterator I = MyVec.begin(); |
| 115 | { |
| 116 | using namespace std; |
| 117 | list<int>::iterator I = MyList.begin(); |
| 118 | } |
| 119 | |
| 120 | // The type specifier for J would transform to auto since it's a typedef |
| 121 | // to a standard iterator type. |
| 122 | typedef std::map<int, std::string>::const_iterator map_iterator; |
| 123 | map_iterator J = MyMap.begin(); |
| 124 | |
| 125 | // The following implementation-specific iterator type for which |
| 126 | // std::vector<int>::iterator could be a typedef would not be transformed. |
| 127 | __gnu_cxx::__normal_iterator<int*, std::vector> K = MyVec.begin(); |
| 128 | |
| 129 | * The initializer for the variable being declared is not a braced initializer |
| 130 | list. Otherwise, use of ``auto`` would cause the type of the variable to be |
| 131 | deduced as``std::initializer_list``. |
| 132 | |
| 133 | Known Limitations |
Edwin Vane | 8d28646 | 2013-06-14 15:14:20 +0000 | [diff] [blame] | 134 | ================= |
Edwin Vane | 3b9f08d | 2013-03-08 23:26:00 +0000 | [diff] [blame] | 135 | * If the initializer is an explicit conversion constructor, the transform will |
| 136 | not replace the type specifier even though it would be safe to do so. |
| 137 | * User-defined iterators are not handled at this time. |