gsl-lite / gsl-lite

gsl-lite – A single-file header-only version of ISO C++ Guidelines Support Library (GSL) for C++98, C++11, and later
MIT License
890 stars 108 forks source link

gsl::span works differently than std::span in terms of type matching? #348

Closed harsszegi closed 10 months ago

harsszegi commented 10 months ago

Hi,

I have a code like this:

#include <cstdint>
#include <gsl/gsl-lite.hpp>

class Foo
{
public:
  void setlist(const gsl::span<double> & list) { this->listd = list; }
  void setlist(const gsl::span<uint32_t> & list) { this->listi = list; }

private:
  gsl::span<double> listd;
  gsl::span<uint32_t> listi;
};

int main()
{
  Foo f;

  double arr1[] = {1.0,2.0,3.0,4.0,5.0};
  uint32_t arr2[] = {11,12,13,14,15};

  f.setlist(arr1);
  f.setlist(arr2);
}

If I use std::span it compiles fine, however with gsl::span it says for both setlist calls that the overloaded calls are ambigous. Is there an explicit reason for this? (Same happens with std::array, however with std::vector it works fine). And obviously with explicit casting the inputs to gsl::span it also compiles fine. What do I miss? Thanks,

mbeutel commented 10 months ago

What do I miss?

Modern defaults. The code compiles fine with version-1 defaults (godbolt).

The ambiguity stems from an unconstrained conversion constructor which has been deprecated a while ago. It is replaced by a constrained version if modern defaults are enabled: https://github.com/gsl-lite/gsl-lite/blob/34ba5141492a88912e2055e08cd1bdd6714431c5/include/gsl/gsl-lite.hpp#L3770-L3784

To enable version-1 defaults, define the preprocessor macro gsl_CONFIG_DEFAULTS_VERSION=1, or if you consume gsl-lite via CMake, simply reference the gsl::gsl-lite-v1 target rather than just gsl::gsl-lite. See https://github.com/gsl-lite/gsl-lite#version-semantics for more details on semantic differences between the versioned defaults.

harsszegi commented 10 months ago

Yeeha, and of course it works just fine! Thanks a lot @mbeutel !