Closed bogiord closed 8 years ago
Thanks for the detailed issue report @bogiord.
I took a look at the current source for span
and here's what I found:
std::array
definitely participate in overload resolution with their current definition, so I think this is resolved at this point.element_type
on those constructors. There should now be additional tests that cover all the const
-qualified permutations of std::array
and its element_type
. If you see something you think is missing, feel free to offer a test case that describes it.I'll close out this issue now, as I think enough of the span
interface has changed that any further discussion probably deserves a fresh thread to avoid confusion. Thanks again for the feedback!
Sorry for the long list of issues, but they're all related; I don't think splitting the list into several issues would help.
The constructor template taking a
const std::array<...>&
will never be used, as theT
template parameter cannot be deduced, so specializations of this template will never participate in overload resolution. Because of this, construction fromconst std::array<...>
falls back to generic construction from containers (Cont&
).I'm not sure about the reason for using
std::remove_const_t<value_type>
as the element type for thestd::array
parameter, but, anyway,T
either goes here or goes away completely.Both constructor templates taking lvalue references to
std::array
specializations usestd::is_convertible<T(*) [], std::remove_const_t<value_type>(*) []>
. Some minor issues are that the first one has a redundanttypename
, and the second one has a typo at the end, so it won't work.More importantly, I'm not sure I understand the reason for using
std::remove_const_t
. Removingconst
from the top level qualifiers of the array element type (which also removes it from the qualifiers of the array itself) basically ensures that the conversion will only work ifT
andstd::remove_const_t<value_type>
are exactly the same type. In order to allow some qualification conversion between the two pointer types, the destination type would have to haveconst
in the qualifiers of the upper levels of its cv-qualification signature.I think allowing qualification conversions here would be fine, just like for built-in arrays. I'd use
std::is_convertible<T(*) [], value_type(*) []>
, coupled with an additional check forstd::is_const<value_type>
when taking aconst std::array<...>
(or maybe using someSpanStdArrayTraits
to addconst
toT
itself in this case... but this may just be overkill). By the way, I think this additional test should also be added as astatic_assert
to the constructor template takingCont&
whenCont
is_const
, to provide a better error message.const std::array<T, N>&&
. Otherwise,const
rvalues will end up with the constructor template takingconst std::array<T, N>&
(once it's fixed), which means construction fromconst
rvalues will be allowed.The deleted constructor template taking
Cont&&
isexplicit
, which means it will be ignored for copy-initialization - arguably the most common scenario for initializing aspan<T>
. This means, for example, that copy-initialization from aconst
container rvalue will work through the constructor template takingCont&
(on MSVC, even non-const
ones will work, due to the infamous non-conforming extension).Which reminds me: the tests in
span_tests.cpp
use direct-initialization in most cases. I think there should be at least as many copy-initializations in there, in order to catch issues like the one above.Also, it seems that the continuous integration tests don't use
CONFIRM_COMPILATION_ERRORS
; otherwise, they should have caught this one, which doesn't fail, as explained above.span<...>
: shouldn't the convertibility test be something likestd::is_convertible<OtherValueType(*)[], ValueType(*)[]>
? I mean, the way it's written now, the test would yieldtrue
fordouble
andint
(double
is convertible toint
), but we don't want to view an underlying array ofdouble
through aspan<int>
. On the other hand, qualification conversions should be fine.