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) という名前で表示されます。

参考資料