枚举与constexpr std :: string_view vs实例化enum与std :: string

时间:2018-04-01 12:35:08

标签: c++ enums static constexpr

我希望struct持有enum进行迭代,同时std::string保留其名称以创建菜单条目。我正在使用这样的东西:

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;
}

据我所知,这是全局变量的首选。它可以工作,但需要在使用前进行实例化。现在,我发现了这个方法,需要--std=C++17来编译:

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;
}

但就内存使用而言,与我之前的做法相比,这将如何表现呢?或者我是怎么做错的?什么是更好的方式?

2 个答案:

答案 0 :(得分:2)

你问的问题并不完全清楚,但除了你的例子中的一些小错误外,没关系。

如果我们稍微更改示例以不使用iostream(因为它与汇编列表中的那么多代码混淆)。一个例子,而不是总结名称的大小:

#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;
}

它编译成一些表示“返回6”的汇编指令。但是,正如加利克指出的那样,不需要枚举技巧。

https://godbolt.org/g/ot2kpt

您还可以选择要循环的范围,如下所示:

for(auto n = std::begin(S::names)+1; n != std::end(S::names); ++n)

答案 1 :(得分:2)

使用enum时,您不需要std::array。你可以这样做:

struct S
{
    static constexpr std::array<std::string_view, 2> names { "one", "two" };
};

int main()
{
    for(auto name: S::names)
        std::cout << name << '\n';
}

或者这个:

int main()
{
    for(auto n = std::begin(S::names); n != std::end(S::names); ++n)
        std::cout << *n << '\n';
}

这与您的第一个示例非常不同,但是因为现在您只有 一个 sruct S一个数组。之前,每个结构都有自己的数组副本。

那么做什么适合你的需要。每个对象一个数组?或者所有你的对象的一个​​数组?