Skip to content

[DataBinder] Avoid std::span/iter_move ambiguity on MSVC STL#510

Merged
christianparpart merged 1 commit into
masterfrom
fix/sqldynamicbinary-msvc-span-itermove
Jun 19, 2026
Merged

[DataBinder] Avoid std::span/iter_move ambiguity on MSVC STL#510
christianparpart merged 1 commit into
masterfrom
fix/sqldynamicbinary-msvc-span-itermove

Conversation

@christianparpart

Copy link
Copy Markdown
Member

Problem

SqlDynamicBinary exposes its byte payload as std::span<value_type const> (the constructor parameter, Bytes(), and the deprecated ToStringView()).

On Microsoft's STL, instantiating std::span<uint8_t const> realizes its std::reverse_iterator specialization, which declares the legacy std::iter_move hidden friend. Once that overload is visible in a translation unit, the unqualified iter_move call inside std::ranges::enumerate_view's iterator becomes ambiguous between it and the std::ranges::iter_move CPO. Any translation unit that both instantiates SqlDynamicBinary and uses std::views::enumerate then fails to compile:

error C2872: 'iter_move': ambiguous symbol

It reproduces with cl.exe under /O2 (force-inlining realizes the span iterator machinery). clang-cl, libstdc++ and libc++ are unaffected — it is a known MSVC STL interaction, not a defect in this library.

Fix

Introduce a ByteView alias and select the view type per standard library:

  • std::basic_string_view<value_type> on MSVC's STL (_MSVC_STL_VERSION) — its iterators do not pull the conflicting iter_move into scope;
  • std::span<value_type const> everywhere else.

std::span is retained off-MSVC because std::basic_string_view<uint8_t> is ill-formed there (no std::char_traits specialization for unsigned char), which is why the span form was adopted originally.

No public API changes beyond the view type alias; Bytes()/ToStringView() keep their contract.

SqlDynamicBinary exposes its byte payload as std::span<value_type const>
(constructor parameter, Bytes(), and the deprecated ToStringView()). On
Microsoft's STL, instantiating std::span<uint8_t const> realizes its
std::reverse_iterator specialization, which declares the legacy
std::iter_move hidden friend. Once that overload is visible in a translation
unit, the unqualified iter_move call inside std::ranges::enumerate_view's
iterator becomes ambiguous between it and the std::ranges::iter_move CPO,
so any translation unit that both instantiates SqlDynamicBinary and uses
std::views::enumerate fails with:

    error C2872: 'iter_move': ambiguous symbol

It reproduces with cl.exe under /O2 (force-inlining realizes the span
iterator machinery); clang-cl and libstdc++/libc++ are unaffected, and it is
a known MSVC STL interaction rather than a defect in this library.

Introduce a ByteView alias and select the view type per standard library:
std::basic_string_view<value_type> on MSVC's STL (its iterators do not pull
the conflicting iter_move into scope), std::span<value_type const>
elsewhere. std::span is retained off-MSVC because std::basic_string_view<uint8_t>
is ill-formed there (no std::char_traits specialization for unsigned char),
which is the reason the span form was adopted in the first place.

Signed-off-by: Christian Parpart <c.parpart@lastrada.net>
@christianparpart christianparpart requested a review from a team as a code owner June 19, 2026 12:37
@github-actions github-actions Bot added the Data Binder SQL Data Binder support label Jun 19, 2026
@christianparpart christianparpart merged commit 85c180a into master Jun 19, 2026
28 checks passed
@christianparpart christianparpart deleted the fix/sqldynamicbinary-msvc-span-itermove branch June 19, 2026 15:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Data Binder SQL Data Binder support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant