clang で range-based for の暗黙コピーを警告するには、-Wrange-loop-analysis
オプションを指定します。
次の例では const pair<const int, int>&
で値を受け取るべきところを const pair<int, int>&
で受けてしまっているため、余分なコピーが発生します。
sample1.cpp
#include <map>
int main()
{
std::map<int, int> m = {
{1, 1},
{2, 4},
{3, 9},
{4, 16},
};
for (const std::pair<int, int>& kv : m)
{
printf("%d x %d = %d\n", kv.first, kv.first, kv.second);
}
return 0;
}
$ # M1 Mac (Ventura) + Apple clang 14.0.0
$ clang sample1.cpp -std=c++17 -lc++ -o sample -Wrange-loop-analysis
sample1.cpp:11:37: warning: loop variable 'kv' of type 'const std::pair<int, int> &' binds to a temporary constructed from type 'std::__map_iterator<std::__tree_iterator<std::__value_type<int, int>, std::__tree_node<std::__value_type<int, int>, void *> *, long>>::reference' (aka 'pair<const int, int> &') [-Wrange-loop-construct]
for (const std::pair<int, int>& kv : m)
^
sample1.cpp:11:10: note: use non-reference type 'std::pair<int, int>' to make construction explicit or type 'const std::__map_iterator<std::__tree_iterator<std::__value_type<int, int>, std::__tree_node<std::__value_type<int, int>, void *> *, long>>::value_type &' (aka 'const pair<const int, int> &') to prevent copying
for (const std::pair<int, int>& kv : m)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 warning generated.
$ ./sample
1 x 1 = 1
2 x 2 = 4
3 x 3 = 9
4 x 4 = 16
プログラムを次のように修正し、const pair<const int, int>&
で受けるようにすれば警告は発生しません。
sample2.cpp
#include <map>
int main()
{
std::map<int, int> m = {
{1, 1},
{2, 4},
{3, 9},
{4, 16},
};
for (const std::pair<const int, int>& kv : m)
{
printf("%d x %d = %d\n", kv.first, kv.first, kv.second);
}
return 0;
}
$ # M1 Mac (Ventura) + Apple clang 14.0.0
$ clang sample2.cpp -std=c++17 -lc++ -o sample -Wrange-loop-analysis
$
警告を抑制する
逆に、警告を抑制したい場合は -Wno-range-loop-analysis
オプションを指定します。 このオプションを指定することで、既に指定されたオプションを打ち消すことができます。
$ # M1 Mac (Ventura) + Apple clang 14.0.0
$ clang sample1.cpp -std=c++17 -lc++ -o sample -Wno-range-loop-analysis
$
Xcode での取り扱い
この警告は、Xcode 上で “Range-based For Loops” (CLANG_WARN_RANGE_LOOP_ANALYSIS
) という名前で表示されます。
参考資料
-
range-based for loopsの要素の型について
https://qiita.com/rinse_/items/cdfce8aa6a685a8ebe0c -
Range based forとauto&&によるperfect forwarding
http://peng225.hatenablog.com/entry/2016/08/10/224044 -
Clang documentation — DIAGNOSTIC FLAGS IN CLANG
https://clang.llvm.org/docs/DiagnosticsReference.html#wrange-loop-analysis -
D4169 Add -Wrange-loop-analysis to warn when a range-based for-loop is creating a copy.
https://reviews.llvm.org/D4169