The prior release(s) contained the following overloads of stlsoft::count_bits():
unsigned
count_bits(
uint32_t v
) /* noexcept */
;
unsigned
uint64_t v
) /* noexcept */
;
Pretty discoverable - either pass a 32-bit or a 64-bit unsigned integer. All the use-cases up to now for which I've needed this function have involved one of those types.
However, a new, and probably widely-applicable, use-case popped up. I have a CLI Windows program pown that prints the ownership of a file/directory. It recognises a number of CLI flags, some of which are mutually exclusive, and combines them into a flags parameter (of type int) that is then passed into the program logic.
Some of the mutually-exclusive flag pertain to how the file path should be shown:
CLI flag | Enumerator |
---|---|
'--show-file-rel-path' | POWN_F_SHOW_FILE_REL_PATH (0x0010) |
'--show-file-path' | POWN_F_SHOW_FILE_PATH (0x0020) |
'--show-file-stem' | POWN_F_SHOW_FILE_STEM (0x0040) |
POWN_F_SHOW_FILE_MASK_ (0x00f0) |
The last enumerator, POWN_F_SHOW_FILE_MASK_, is a mask for the show-file flags. In order to verify that, at most, a single relevant flag had been specified was code such as the following:
if (stlsoft::count_bits(flags & POWN_F_SHOW_FILE_MASK_) > 1)
{
. . . // issue contingent report, and ...
return EXIT_FAILURE; // ... exit the program
{
. . . // issue contingent report, and ...
return EXIT_FAILURE; // ... exit the program
}
What I needed was an overload that takes an int. But which overload should it invoke?
I could just cast an int to a uint64_t, but I didn't want to risk any performance costs in code generation in any of the many (versions of) compilers that are supported. Instead, it felt like an opportunity for some, admittedly pretty simple, template metaprogramming.
Without further ado, here's the implementation (with documentation and other stuff elided for brevity):
#ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
template <size_t N_bytes>
unsigned
count_bits_int_(
int v
);
template <>
unsigned
int v
)
{
return count_bits(static_cast(v));
}
template <>
int v
)
{
return count_bits(static_cast(v));
}
#endif /* !STLSOFT_DOCUMENTATION_SKIP_SECTION */
unsigned
int v
)
{
return count_bits_int_<sizeof(int)>(v);
}
No comments:
Post a Comment