C++ 有没有一种方法可以在不知道枚举大小的情况下在c++;

C++ 有没有一种方法可以在不知道枚举大小的情况下在c++;,c++,c++11,C++,C++11,你好,我有下面的枚举 enum params_Solver { params_Solver_Lorem, params_Solver_Ipsum, params_Solver_Simply, params_Solver_Dummy, params_Solver_Test, params_Solver_Typesetting, params_Solver_Industry, params_Solver_Scrambled }; 我想做的是尝试做如下伪代码: for

你好,我有下面的枚举

enum params_Solver {
  params_Solver_Lorem,
  params_Solver_Ipsum,
  params_Solver_Simply,
  params_Solver_Dummy,
  params_Solver_Test,
  params_Solver_Typesetting,
  params_Solver_Industry,
  params_Solver_Scrambled
};
我想做的是尝试做如下伪代码:

for (auto enum_member: params_Solver)
{
    print(index, enum_member); // output looks like this: "0, params_Solver_Lorem", "1, params_Solver_Ipsum" etc
}
有没有办法做到这一点


编辑:我无法控制枚举。此枚举由第三部分库中的不同文件提供。我可能可以复制它,但不能更改原始枚举。我想将枚举库的成员写入另一个文件。

通用方式

您可以通过以下方式在枚举末尾添加项:

enum参数求解器{
params_Solver_Lorem,
参数,
params_Solver_简单地说,
参数解算器虚拟,
参数解算器测试,
参数解算器排版,
params_Solver_工业,
params_Solver_乱了阵脚,
最后
};
并在其上循环:

for(int i=params\u Solver\u Lorem;i!=Last;i++){
//一些代码
}
但是,如果将值指定给枚举成员而不是默认成员,则此解决方案不起作用

其他方式

您可以使用常规数组,而无需添加最后一个元素。但是,由于您必须自己指定枚举的成员,因此语法非常冗余:

constexpr参数解算器成员[]{
params_Solver_Lorem,
参数,
params_Solver_简单地说,
参数解算器虚拟,
参数解算器测试,
参数解算器排版,
params_Solver_工业,
参数被置乱
};
然后,可以使用以下命令在枚举上迭代:

用于(自动m:成员){
//一些代码
}

不。至少不直接。枚举实际上不是一组常量。相反,它们是一种带有一组命名常量的类型。区别在于:例如,
42
params_Solver
的完全有效值,它只是没有名称

启用迭代的常见方法是添加sentinel值:

enum params_Solver {
  params_Solver_Lorem,
  params_Solver_Ipsum,
  params_Solver_Simply,
  params_Solver_Dummy,
  params_Solver_Test,
  params_Solver_Typesetting,
  params_Solver_Industry,
  params_Solver_Scrambled,
  num_params_Solver          // <----
};
enum参数求解器{
params_Solver_Lorem,
参数,
params_Solver_简单地说,
参数解算器虚拟,
参数解算器测试,
参数解算器排版,
params_Solver_工业,
params_Solver_乱了阵脚,

num_params_Solver/枚举的基础类型中可表示的所有值都是枚举的有效值,无论它们是否具有名称,在64位枚举范围内迭代可能需要比您愿意等待更长的时间……)

另一个复杂的问题是,如果您想只迭代指定的枚举数,这是可能的,但需要更多的工作和一些考虑因素。如前所述,如果您不为枚举数提供任何自定义值,那么它们将从零开始并递增。但是,您可以在数字中设置间隙,也可以向后跳,也可以使用repeats。两个具有相同值的枚举数是作为一个迭代计数还是每个名称计数?不同的情况会有不同的答案

如果在没有为枚举数自定义值的情况下执行此操作,则可以在列表末尾添加一个额外的“伪”值,并将其视为枚举数的计数。但是,如果存在间隙、重复或从0以外的值开始,则这将是错误的。如果有人在伪值之后添加新的枚举数值,此操作也可能失败

有一些第三方库可以提供帮助。如果您不介意一些额外的代码,“Better Enums”开源库是非常有用的仅头库。
它通过一个漂亮的语法在枚举上提供元数据,允许迭代器、循环使用范围、转换为字符串名称或其他名称。

C++不提供对您尝试执行的操作的内在支持

您可以添加一些样板文件来完成所需的操作,以便使用枚举范围的代码不知道枚举。在代码示例中,这些知识封装在
params\u Solver\u range
helper类中

#include <iostream>
#include <stdexcept>
#include <utility>

using std::ostream;
using std::cout;
using std::underlying_type_t;
using std::logic_error;

namespace {

enum class params_Solver {
    Lorem,
    Ipsum,
    Simply,
    Dummy,
    Test,
    Typesetting,
    Industry,
    Scrambled
};

auto operator<<(ostream& out, params_Solver e) -> ostream& {
#define CASE(x) case params_Solver::x: return out << #x
    switch(e) {
        CASE(Lorem);
        CASE(Ipsum);
        CASE(Simply);
        CASE(Dummy);
        CASE(Test);
        CASE(Typesetting);
        CASE(Industry);
        CASE(Scrambled);
    }
#undef CASE

    throw logic_error("unknown params_Solver");
}

auto operator+(params_Solver e) {
    return static_cast<underlying_type_t<decltype(e)>>(e);
}

auto operator++(params_Solver& e) -> params_Solver& {
    if (e == params_Solver::Scrambled) throw logic_error("increment params_Solver");
    e = static_cast<params_Solver>(+e + 1);
    return e;
}

class params_Solver_Range {
    bool done = false;
    params_Solver iter = params_Solver::Lorem;

public:
    auto begin() const -> params_Solver_Range const& { return *this; }
    auto end() const -> params_Solver_Range const& { return *this; }
    auto operator*() const -> params_Solver { return iter; }
    bool operator!=(params_Solver_Range const&) const { return !done; }
    void operator++() {
        if (done) throw logic_error("increment past end");
        if (iter == params_Solver::Scrambled) done = true;
        else ++iter;
    }
};

} // anon

int main() {
    for (auto e : params_Solver_Range()) {
        cout << +e << ", " << e << "\n";
    }
}
#包括
#包括
#包括
使用std::ostream;
使用std::cout;
使用std::基础类型;
使用std::logic\u错误;
名称空间{
枚举类参数求解器{
洛勒姆,
乱数假文,
简单地说,
笨蛋,
测试,
排版,
工业,,
爬
};
自动运算符params_Solver_Range const&{return*this;}
auto end()const->params_Solver_Range const&{return*this;}
自动运算符*()常量->参数求解器{return iter;}
布尔运算符!=(参数解算器范围常数&)常数{return!done;}
void运算符++(){
如果(完成)抛出逻辑_错误(“增量超过结束”);
if(iter==params_Solver::Scrambled)done=true;
else++iter;
}
};
}//阿农
int main(){
用于(自动e:params_Solver_Range()){

coutNo。您想要的反射建议可能会在[c++23]中到达

如果没有它,您可以将
枚举
复制粘贴到数组中,并可能引用它,然后在副本上迭代

constexpr char const* members[] {
  "params_Solver_Lorem",
  "params_Solver_Ipsum",
  //etc
};
然后在上面做一个for循环

for (char const* const& enum_member: members)
{
  auto index = static_cast<long long unsigned>(&enum_member-members);
  printf("%llu, %s\n", index, enum_member);
}
for(字符常量*常量和枚举成员:成员)
{
自动索引=静态强制转换(&enum\u member-members);
printf(“%llu,%s\n”,索引,枚举成员);
}

.

枚举没有“大小”。您可以将枚举视为常量变量的枚举:
constexprt auto params_Solver_Lorem=0;
constexpr auto params_Solver_Ipsum=1;
…无法以可枚举的方式获取变量。传统方法是:
params_Solver_Last//不要移动,保持在末尾
的ODE >循环。你不能同时检索名字。在C++中没有反射。根据这个答案,你仍然需要知道第一个和最后一个值,假设这两个之间没有空隙。这是不是回答了你的问题?为什么<代码> STD::IngaliSeriSList< /COD>?为什么不只是一个数组?实际上我不明白为什么我要去一个
initializer\u list
,如果我使用
std::array
我仍然需要指定元素的数量,那么数组就很好了。我可以使用