问题
I would like to have struct
s holding enum
s for iteration, together with std::string
holding their names for creating menu entries. I was using something like this:
struct S
{
enum E { ONE, TWO, ALL };
std::array<std::string, ALL> names { "one", "two" };
};
int main()
{
S s;
for(int i=s.ONE; i<s.ALL; ++i) // or S::...
std::cout << s.names[i] << '\n';
return 0;
}
As I understand, this is preferred to having global variables. It works, but needs instantiation before usage. Now, I found out about this method, which needs --std=C++17
to compile:
struct S
{
enum E { ONE, TWO, ALL };
static constexpr std::array<std::string_view, ALL> names { "one, "two" };
};
int main()
{
for(int i=S::ONE; i<S::ALL, ++i)
std::cout << S::names[i] << '\n';
return 0;
}
But how will this behave, in terms of memory usage, compared to my previous way of doing this? Or is there a wrong way in how I do it? What would be a better way?
回答1:
You don't need that enum
when using std::array
. You can do this:
struct S
{
static constexpr std::array<std::string_view, 2> names { "one", "two" };
};
int main()
{
for(auto name: S::names)
std::cout << name << '\n';
}
Or this:
int main()
{
for(auto n = std::begin(S::names); n != std::end(S::names); ++n)
std::cout << *n << '\n';
}
This is very different from your first example though because now you only have one array for every sruct S
. Before, every struct has its own copy of the array.
So do what suits your need. One array per object? Or one array for all your objects?
回答2:
It's not completely clear what you ask, but except from a few small errors in your example it's fine.
If we change the example a bit to not use iostream (because it's confusing with that much code in the assembly listing). An example, instead summing the size of the names:
#include <string_view>
#include <array>
struct S
{
enum E { ONE, TWO, ALL };
static constexpr std::array<std::string_view, ALL> names { "one", "two" };
};
int main()
{
int l=0;
for(int i=S::ONE; i<S::ALL; ++i){
l+= S::names[i].size() ;
}
return l;
}
It compiles to a few assembly instructions representing "return 6". But, as Galik points out, no need for the enum trick.
https://godbolt.org/g/ot2kpt
You can also pick a range to loop over, like this:
for(auto n = std::begin(S::names)+1; n != std::end(S::names); ++n)
来源:https://stackoverflow.com/questions/49598101/enum-with-constexpr-stdstring-view-vs-instantiated-enum-with-stdstring