C26486 with string_view

Viewed 150

Compilling the code below in MSVS with c++ core guidlines enabled produces warning:

C26486 LIFETIMES_FUNCTION_PRECONDITION_VIOLATION - Link to relevant Microsoft Docs

using vec_pair = std::vector<std::pair<const std::string_view, const std::string_view>>;

void foo(const vec_pair& vec_pair) noexcept
{
    for (auto [first, second] : vec_pair) //<---- Warning here
    {
        // do stuff
    }
}

int main()
{
    const vec_pair my_vec_pair { {
        {"yes", "no"},
        {"what", "why"},
        {"salt", "pepper"},
    } };

    foo(my_vec_pair);

    return 0;
}

Description is:

Don't pass a pointer that may be invalid to a function. Parameter 0 '$S1' in call to '<move><std::pair<std::basic_string_view<char,std::char_traits<char> > const ,std::basic_string_view<char,std::char_traits<char> > const > & __ptr64>' may be invalid (lifetime.3).

Changing std::string_view to std::string does not help. Nor does checking for nullptr both before and after the for loop.

How should I deal with this?

1 Answers

This is a bug in the Core Guidelines checker. The bug is actually in its understanding of structured bindings to tuple-like types (such as std::pair); a minimal example is:

#include <utility>
void foo(std::pair<int, int> p) noexcept {
    auto const [x, y] = p;
}

It appears that the checker is being confused by the treatment of the invented variable as an xvalue; see Case 2: binding a tuple-like type at Structured binding declaration and dcl.struct.bind. A workaround is to use a ref-qualifier of & so that the invented variable is treated as an lvalue:

#include <utility>
void foo(std::pair<int, int> p) noexcept {
    auto const& [x, y] = p;
    //        ^
}

Live example.

Note: admittedly, that workaround won't work in this case, since it falls foul of C26445: A reference to gsl::span or std::string_view may be an indication of a lifetime issue (gsl.view). If you can't suppress or ignore the warning, you'll have to use first and second like in the old days.

Related