0

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.

2
  • 1
    does not reduce this to bool but to AFE. so cast to uint32_t? Commented Mar 15, 2022 at 8:54
  • 1
    the problem isnt that obvious, because the template parameter is a value not a type Commented Mar 15, 2022 at 9:01

1 Answer 1

2

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>();
}
Sign up to request clarification or add additional context in comments.

1 Comment

In conjunction with your answer and the suggestion by @KamilCuk, I was able to get this to work. Thank you for your help!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.