I'm trying to refactor an entire codebase of "std::filesystem::path path = blah; if (path.extension() == ".whatever") load_file(path) else abort/error".
Thus far, I've written my enum as a bitfield with all the file extensions I wish my application to accept, and this function in the Assets namespace:
enum class AcceptedFileExtension : uint32_t {
SCENE = BIT(0),
OBJ = BIT(1),
GLTF = BIT(2),
GLB = BIT(3),
PNG = BIT(4),
JPG = BIT(5),
TTF = BIT(6),
VERT = BIT(7),
FRAG = BIT(8),
SPV = BIT(9),
};
template <AcceptedFileExtension T>
static std::optional<std::filesystem::path> accept(const std::filesystem::path& path)
{
if (to_accepted_extension(path) == T) {
return { path };
}
return {};
}
where the template type is my enum, defined as a bitfield essentially (Each member is = 1 << n, say for example AcceptedFileExtension::PNG = 1 << 3).
I would like this function to accept logically "or"-d values as the template, e.g:
// AFE = AcceptedFileExtension
auto path_or_nothing = Assets::accept<AFE::PNG | AFE::JPG>(assets_folder_path / images);
I recently read this post on SO and tried to write my own implementation for a new API, which added the logical operators to the enum class I'd written. However, the problem is obvious, this creates a value (?) and not a type which I can use in templates. These are inline constexpr, and implements or, and, xor.
If I then make the enum class into a parameter for the function as an R-value (which is how the caller should use it), another issue arises:
static std::optional<std::filesystem::path> accept(const std::filesystem::path& path, AcceptedFileExtension&& afe)
{
// Does not compile, since "&" does not reduce this to bool but to AFE.
if (to_accepted_extension(path) & afe) {
return { path };
}
return {};
}
How do I move forward?
Thank you.
CodePudding user response:
You can write your own overload of operator|
for your enum. E.g.
#include<cstdint>
constexpr uint32_t BIT(int i){
return static_cast<uint32_t>(1)<<i;
}
enum class AcceptedFileExtension : uint32_t {
SCENE = BIT(0),
OBJ = BIT(1),
GLTF = BIT(2),
GLB = BIT(3),
PNG = BIT(4),
JPG = BIT(5),
TTF = BIT(6),
VERT = BIT(7),
FRAG = BIT(8),
SPV = BIT(9),
};
constexpr AcceptedFileExtension operator|(
AcceptedFileExtension const& lhs,
AcceptedFileExtension const& rhs
){
return static_cast<AcceptedFileExtension>(
static_cast<uint32_t>(lhs) |
static_cast<uint32_t>(rhs)
);
}
template <AcceptedFileExtension T>
static void accept()
{
}
int main(){
accept<AcceptedFileExtension::PNG | AcceptedFileExtension::JPG>();
}