0

I have a file which contains arrays of strings representing some icons.

static constexpr char icons1[2][40] = {
  "icon1_A", "icon1_B"
};

static constexpr char icons2[3][30] = {
  "icon22_A", "icon2_B", "icons2_C"
};

Then I have a class that wants to be initialized with a reference to these icons.

class Display {
public:
  Display(const char ** _icons) : icons(_icons), current_icon(0) {}

  void print_next_icon() {
    std::cout << icons[++current_icon] << std::endl;
  }
  
private:
  const char **icons;
  size_t current_icon;
}

I am getting a compiler error when I try to initialize the Display class by passing it the constexpr icons:

Display i1(icons1); 
Display i2(icons2);

I've tried casting it to const char**, but the compiler complains that the cast removes attributes.

1
  • 2
    You've dodged a bullet here by being stopped by the compiler because the attributes are the least of your worries. A char** is not the same as a char [][40], so casting would have left you with a logic error. Commented Nov 9, 2020 at 23:28

1 Answer 1

1

The declaration here is needlessly complicated. Try and keep it simple:

static const char* icons1[] = {
  "icon1_A", "icon1_B"
};

If you're passing these in as arguments and you need to know exactly how many there are it helps to have some kind of terminator:

static const char* icons1[] = {
  "icon1_A", "icon1_B", nullptr
};

Where you can iterate through this list until you hit nullptr and then stop.

constexpr is used for, not surprisingly, const expressions, as in more complex expressions with operators in them and/or functions that you want to evaluate. It's not necessary here since nothing exotic is going on, this is a straight-forward const declaration.

What's worth noting here is that the memory layout of char** and char[3][40] are completely different. In the first case you have an array of pointers, where those pointers refer to arbitrary memory locations, and in the second you have what is effectively a contiguous chunk of 120 bytes, no pointers at all. This cannot be recast to the other form, it requires creating a new array of pointers.

That being said, your function assumes that these pointers will have an indefinite lifespan, which can be risky. It's almost always safer to use std::string, as in std::vector<std::string> to pass these around.

Sign up to request clarification or add additional context in comments.

Comments

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.