Skip to content

Overly permissive constructor #64

@improbablejan

Description

@improbablejan

Hi, we have got a bunch of code in our repository that looks like this (simplified):

#include "span.hpp"
#include <cstddef>
#include <cstdint>

void foo(nonstd::span<std::uint8_t>) {}
void foo(nonstd::span<nonstd::span<std::uint8_t>>) {}

int main() {
  std::uint8_t u;
  foo({&u, 1u});
  return 0;
}

I am looking at upgrading our dependency, and while this used to work fine for us previously (using commit 874fa1b14e75d8ad45f28250caeb518687990c70), this no longer works using the release 0.9.0 as the call to foo is now ambiguous.

$ clang++-12 --std=c++11 span.cc 
span.cc:10:3: error: call to 'foo' is ambiguous
  foo({&u, 1u});
  ^~~
span.cc:5:6: note: candidate function
void foo(nonstd::span<std::uint8_t>) {}
     ^
span.cc:6:6: note: candidate function
void foo(nonstd::span<nonstd::span<std::uint8_t>>) {}
     ^
1 error generated.

This code also seems to work fine with gcc and clang's implementation of std::span, see https://gcc.godbolt.org/z/Y657dh

We presume this is due to some constructors being overly permissive and participating in overload resolution where they should not, but we have not looked into which particular one is the issue and this is just a hypothesis, so apologies if the title is inaccurate. I haven't checked the standard in detail to understand if this is supposed to work or not, but presume that the ambiguity is due to an oversight rather than by the standard - apologies if that's not the case!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions