Skip to content

popcount uintN_t for N!=32 problem #8

@prlw1

Description

@prlw1

P2933R4 brings in overloads for <bit> functions.

Trying the following example (with g++ 16.0.0 20250827 -std=c++26 on NetBSD)

#include <bit>
#include <cstdint>
#include <print>
#include <simd>

int main() {
        using V = typename std::datapar::simd<std::uint8_t, 16>;
        V vec = std::datapar::iota<V>;
        for (std::size_t i{}; i != V::size; ++i) {
                std::println("{:4b}:{}", vec[i], std::popcount(vec[i]));
        }
/*
        auto pc = std::datapar::popcount(vec);
        for (std::size_t i{}; i != V::size; ++i) {
                std::println("{:4b}:{}", vec[i], pc[i]);
        }
*/
}

the above compiles and runs as is.

If the commented-out code is reinstated, compilation fails with

In file included from /usr/src/local/simd/simd:20,
                 from popcount.cc:4:
/usr/src/local/simd/bits/simd_bit.h: In instantiation of 'constexpr std::datapar::rebind_t<typename std::make_signed<typename _Vp::value_type>::type, _Vp> std::datapar::popcount(const _Vp&) [with _Vp = basic_simd<unsigned char, std::_VecAbi<16> >; rebind_t<typename std::make_signed<typename _Vp::value_type>::type, _Vp> = basic_simd<signed char, std::_VecAbi<16> >; typename std::make_signed<typename _Vp::value_type>::type = signed char; typename _Vp::value_type = unsigned char]':
required from here
popcount.cc:13:34:   
   13 |         auto pc = std::datapar::popcount(vec);
      |                   ~~~~~~~~~~~~~~~~~~~~~~^~~~~
/usr/src/local/simd/bits/simd_bit.h:106:14: error: use of deleted function 'constexpr std::datapar::basic_simd<_Tp, _Abi>::basic_simd(_Fp&&) [with _Fp = std::datapar::popcount<basic_simd<unsigned char, std::_VecAbi<16> > >(const basic_simd<unsigned char, std::_VecAbi<16> >&)::<lambda(int)>; _Tp = signed char; _Abi = std::_VecAbi<16>]': Invalid return type of the generator function: Requires value-preserving conversion or implicitly convertible user-defined type.
  106 |       return _Rp([&](int __i) { return std::popcount(__v[__i]); });
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/src/local/simd/simd:12:
/usr/src/local/simd/bits/simd.h:166:9: note: declared here
  166 |         basic_simd(_Fp&& )
      |         ^~~~~~~~~~
/usr/src/local/simd/bits/simd_bit.h:106:14: note: use '-fdiagnostics-all-candidates' to display considered candidates
  106 |       return _Rp([&](int __i) { return std::popcount(__v[__i]); });
      |              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*** Error code 1

If uint8_t is replaced with uint32_t, then all is well again.

Apart from the principle of least surprise, I think

The type V::value_type is an unsigned integer type

should work for any uintN_t?

Metadata

Metadata

Assignees

Labels

needs testA test is missing to verify this can't happen again

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions