Skip to content

[BUG]: std::span fails direct-list-initialization {ptr, size} due to incorrect narrowing conversion analysis. #7659

@VirajsNexus

Description

@VirajsNexus

Is this a duplicate?

Type of Bug

Compile-time Error

Component

libcu++

Describe the bug

std::span Brace-Initialization Bug (C++20)

Issue Summary

According to the final C++20 standard, std::span should support construction via:

span(pointer, size_type)

using brace-initialization without ambiguity:

std::span<const bool> s{ptr, size};

However, some compilers incorrectly prioritize element-wise initialization (or an obsolete initializer_list constructor), resulting in false-positive narrowing conversion errors.


Description

When initializing a std::span<const bool> with a pointer and a size using brace-initialization:

std::span<bool const> s{ptr, size};

The compiler incorrectly treats ptr and size as values to be contained in the span (attempting to convert them to bool) instead of matching the constructor:

constexpr span(pointer first, size_type count);

This contradicts P1394R4, which removed the initializer_list constructor from std::span specifically to allow {ptr, size} syntax to correctly resolve to the pointer-count constructor.


Environment

  • Standard: C++20
  • Compiler: [Insert Compiler Version, e.g., GCC 10.2, GCC 11.1, Clang 12, etc.]
  • OS: [Insert Operating System]

Related Standards Paper

  • P1394R4Range constructor for std::span
    (Removed initializer_list constructor to allow {ptr, size} syntax.)

Notes

If this behavior persists in newer compiler versions, it may indicate:

  • A library implementation issue
  • An outdated standard library implementation
  • A compiler overload resolution bug

Please verify with the latest compiler and standard library version.

How to Reproduce

Reproduction Code

File: main.cpp

#include <span>
#include <cstddef>

int main() {
  bool data[4] = {true, false, true, false};
  bool* ptr = data;
  size_t size = 4;

  // EXPECTED: Matches span(pointer, size_type) constructor
  // ACTUAL: Fails with narrowing conversion (treats args as elements)
  ::std::span<bool const> bad_span{ptr, size}; 

  return 0;
}

Compilation Steps

Compile with C++20 standard enabled.

GCC / Clang

g++ -std=c++20 -Wnarrowing main.cpp -o test_span
# or
clang++ -std=c++20 -Wnarrowing main.cpp -o test_span

Actual Output

The compiler emits errors indicating it is attempting to convert the pointer and size into bool values:

error: narrowing conversion of 'ptr' from 'bool*' to 'bool' [-Werror=narrowing]
   ::std::span<bool const> bad_span{ptr, size};
                                    ^~~
error: narrowing conversion of 'size' from 'size_t' {aka 'long unsigned int'} to 'bool' [-Werror=narrowing]
   ::std::span<bool const> bad_span{ptr, size};
                                         ^~~~

Expected behavior

Expected Behavior

The code should compile cleanly.

Overload resolution should select:

constexpr span(pointer first, size_type count);

Since std::span is not an aggregate and does not have a constructor taking std::initializer_list (per the final C++20 specification), standard list-initialization rules dictate that the compiler should attempt to match the arguments to a constructor.


Reproduction link

No response

Operating System

No response

nvidia-smi output

No response

NVCC version

No response

Metadata

Metadata

Assignees

Labels

libcu++For all items related to libcu++

Type

Projects

Status

Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions