-2

The following is a toy example:

An image stores a width, height and filepath, represented by the struct IMAGE:

#include <cstdlib>
#include <type_traits>
struct IMAGE {
    int WIDTH;
    int HIGHT;
    const char* FILEPATH;
};
static_assert(std::is_pod<IMAGE>::value);

There are a 100 unique IMAGEs in a game such as a Dirt Block, a Sword, and a Main Menu etc. One approach (1) to storing all these 100 images in a program is to use separate variables for each unique image:

int main(){
    IMAGE DIRTBLOCK = IMAGE(25, 25, "RESOURCE\\DIRTBLOCKIMAGE");
    IMAGE SWORD = IMAGE(100, 25, "RESOURCE\\SWORDIMAGE");
    IMAGE MAINMENU = IMAGE(500, 500, "RESOURCE\\MAINMENUIMAGE);
}

Another approach (2) could be to use an enum of Image Names and an array of IMAGEs:

enum IMAGENAME : unsigned char {
    DIRTBLOCK,
    SWORD,
    MAINMENU,
    NUMIMAGES
};

IMAGE* IMAGES; 

int main(){
    IMAGES = (IMAGE*)std::malloc(sizeof(IMAGE) * NUMIMAGES);
    IMAGES[DIRTBLOCK] = IMAGE {25, 25, "RESOURCE\\DIRTBLOCKIMAGE"};
    IMAGES[SWORD] = IMAGE {100, 25, "RESOURCE\\SWORDIMAGE"};
    IMAGES[MAINMENU] = IMAGE {500, 500, "RESOURCE\\MAINMENUIMAGE"};
    std::free(IMAGES);
}

Generally, What are the advantages and disadvantages of approaches (1), (2). Alternatively, is there a better approach(3), I have not considered.

I am relatively new to c++, so your help is appreciated.

49
  • 2
    stackoverflow.com/questions/184537/… - but note that you shouldn't have to do your own memory management for this, so use a std::vector<IMAGE>. Commented Feb 28 at 2:14
  • 2
    @timmygeorge How is using malloc and free simpler than this? Every C++ programmer is familiar with std::vector. It's one of the first things people learn, along with std::string. If there is a fixed number of IMAGEs, you could instead use a std::array, like this. Commented Feb 28 at 2:20
  • 5
    vector is complicated, but using vector is close to brainless. It's like driving a car. Any fool can drive a car, but it's takes some mad skills to build one. Commented Feb 28 at 2:27
  • 2
    high_resolution_clock is just an alias for stready_clock in MSVC. high_resolution_clock should however not be used. Even its inventor says so. Re: "It is my firm belief you should learn the C way of doing things before the C++ way of doing things" - you'll find that most experienced C++ programmers will disagree with that. Commented Feb 28 at 4:31
  • 2
    @timmygeorge "OP" stands for Original Poster. As to learning C before C++, see what the C++ FAQ says. Commented Feb 28 at 4:38

1 Answer 1

2

I came up with a solution based on the suggestion of Ted Lyngmo. I'm not expecting reputation points for this. I only want to show timmy george a possible solution in reasonable C++. Live code.

The container used is an unordered_map. The IMAGENAME enum is the key, and IMAGEs are the value. The container can be walked directly with a range-for or a standard for with the addition of the increment() increasing the value of the enum iterator. Care must be taken not to exceed the range of the enum.

My additional comment is to break from C naming and use a C++ convention. I would change IMAGENAME to ImageName and IMAGE to Image. Similarly, rename the enums to DirtBlock and the member fields to mWidth. In short, stop shouting in your code. LOL

#include <print>
#include <unordered_map>
using std::println, std::print;

enum IMAGENAME : unsigned char { DIRTBLOCK, SWORD, MAINMENU, NUMIMAGES, LASTIMAGE };

void increment(IMAGENAME& in) {
   in = static_cast<IMAGENAME>(static_cast<int>(in) + 1);
}
struct IMAGE {
    int WIDTH;
    int HEIGHT;
    const char* FILEPATH;
};

std::unordered_map<IMAGENAME, IMAGE> images{
    {DIRTBLOCK, IMAGE{25, 25, "RESOURCE\\DIRTBLOCKIMAGE"}},
    {SWORD, IMAGE{25, 25, "RESOURCE\\SWORDIMAGE"}},
    {MAINMENU, IMAGE{25, 25, "RESOURCE\\MAINMENUIMAGE"}},
};

auto main() -> int {
    for (auto const& image : images) {
        println("{}", image.second.FILEPATH);
    }
    println("");


   for (IMAGENAME in{}; in != NUMIMAGES; increment(in)) {
      println("{}", images.at(in).FILEPATH);
   }

    return 0;
}
Sign up to request clarification or add additional context in comments.

5 Comments

Normally my conventions are Pascal case for variables and functions, screaming case for macros and flatcase for type-aliases and classes. However I chose screaming case for the code above to see how it looks like if you did all screaming case.
Doesn't a HashMap take significantly more time than array indexing since the key is hashed. Also isnt there a chance of collisions as well (although very low)?
@timmygeorge Your requirement is to use the enum to access the values. If you want faster access, use an std:;vector and keep it and the enums aligned. You stated 100 images, which is not going to cause a collision.
ok. Thanks for the answer
A note about ALLCAPS: By long-standing convention, ALLCAPS identifiers are reserved for macro-defined constants as a warning to readers that preprocessor text substitution is in play.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.