microsoft / microsoft/STL

STL: `expected<any, T>` and its friends can break container iterator comparison

Open
#4,847 12 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
C++
Stars
11.2k
Forks
1.7k
Avg merge
4d 15h
Merged PRs (30d)
22

Description

Describe the bug

The bug reported in GCC Bugzilla #115939 is currently also present in MSVC STL. Iterator comparison is currently broken for all but set containers.

The reason of the bug is that expected<any, T> is so permissive on implicit conversion that operator== for expected can cause ambiguity. Note that while there may be a defect in expected, such ambiguity can also caused by some (misdesigned) user-defined types in C++14 mode.

Command-line test case

Godbolt link

#include <any>
#include <expected>

#include <vector>
#include <forward_list>
#include <deque>
#include <list>
#include <array>
#include <map>
// #include <set> // possibly fine
#include <unordered_map>
// #include <unordered_set> // possibly fine

int main()
{
    {
        std::array<std::expected<std::any, char>, 1> cont{};
        (void)(cont.begin() == cont.end());
    }
    {
        std::vector<std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }
    {
        std::forward_list<std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }
    {
        std::list<std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }
    {
        std::deque<std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }

    {
        std::map<int, std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }
    {
        std::multimap<int, std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }
    {
        std::unordered_map<int, std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }
    {
        std::unordered_multimap<int, std::expected<std::any, char>> cont;
        (void)(cont.begin() == cont.end());
    }
}

Expected behavior

This program compiles and operator== overloads for iterators are selected.

STL version

Microsoft Visual Studio Community 2022
Version 17.11.0 Preview ? (14.41.33923 from Godbolt)

Still present in 17.11.0 Preview 4.0 and ecbc1efa09936f4ef5af529e770a95a29a4290d3.

Additional context

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by compiling the provided reproducer with , , and the listed container headers, then inspect the iterator operator== overloads involved in the ambiguity. Check the behavior across the containers in the example, including the set cases, and confirm that each comparison compiles with the intended iterator overload selected.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.