为什么我不能使外部类型看起来像 c++ 中的内部类型?
Why can't I make a external type appear like an inner type in c++?
我想维护一个大量使用内部枚举的现有API,但我需要将枚举分离为自己的类型:
这是当前的API:
class Outer {
public:
enum Inner {
FIELD1
};
};
换句话说,用户当前期望通过使用Outer::Inner
来设置Inner
s。如果可能的话,当我制作新的外部类型时,我想保留这个名称:
enum Inner {
FIELD1
};
class Outer {
public:
typedef Inner Inner;
}
然而,它给了我一个编译器错误:
./Playground/file0.cpp:23:19: error: declaration of 'typedef enum Inner Outer::Inner' changes meaning of 'Inner' [-fpermissive]
23 | typedef Inner Inner;
| ^~~~~
./Playground/file0.cpp:17:6: note: 'Inner' declared here as 'enum Inner'
17 | enum Inner {
| ^~~~~
如果我只是更改枚举的名称,一切都很好。
#include <cassert>
enum Enum {
FIELD1
};
class Outer {
public:
typedef Enum Inner;
};
int main() {
Enum field = Enum::FIELD1;
Outer::Inner field_alt = Outer::Inner::FIELD1;
assert(field == field_alt);
return 0;
}
Inner
的typedef
需要引用外部范围中的Inner
枚举,因此它应该如下所示:
typedef ::Inner Inner;
不过,我通常更喜欢using
语句,它看起来像这样:
using Inner = ::Inner;
这是的演示
由于规则[basic.scope.class]/3:,这是不允许的
类
S
中使用的名称N
在其上下文中以及在S
的完整范围中重新评估时应引用相同的声明。违反此规则不需要进行诊断。
执行typedef Inner Inner;
时,您违反了此规则。Inner
第一次出现在该行时,它是名称的使用,并被发现引用声明::Inner
。但是一旦类被完全定义,Inner
现在引用typedef声明。因此,该程序是格式错误的NDR(GCC足够好,可以为您提供诊断(。
您需要将其更改为:
typedef ::Inner Inner;
现在,不再使用不合格名称Inner
;相反,您使用的是限定名::Inner
,其含义在typedef之后保持不变,因此应该没有问题。
提供的解决方案回答了我最初的问题,但不幸的是,没有解决我的问题。当时我还没有意识到API实际上利用了内部枚举。
enum Inner {
FIELD1,
FIELD2
};
class Base {
public:
virtual void use(Inner val) = 0;
};
class Outer : public Base {
public:
virtual void use(Inner val) override;
};
/*
* Some API that can't change
*/
void someAPI(Outer &inst) {
inst.use(Outer::FIELD1);
}
换句话说,我需要维护的API不是Outer::Inner::FIELD1
,而是Outer::FIELD1
。
正如@Brian所指出的,在当前的c++中,使用typedef将内部枚举"提升"到外部是不可行的。
最终,我发现我可以将Inner放入Base,并且API可以被维护:
class Base {
public:
enum Inner {
FIELD1,
FIELD2
};
virtual void use(Inner val) = 0;
};
class Outer : public Base {
public:
virtual void use(Inner val) override;
};
/*
* Some API that can't change
*/
void someAPI(Outer &inst) {
inst.use(Outer::FIELD1);
}
- ArduinoJson 6.15.2:JsonObject没有命名类型
- 防止主数据类型C++的隐式转换
- 大量序列中核苷酸类型的快速计数
- 如何从C++中的依赖类型中获得它所依赖的类型
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 是否可以初始化不可复制类型的成员变量(或基类)
- 如何获取std::result_of函数的返回类型
- 从父命名空间重载类型
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 访问者访问变体并返回不同类型时出错
- 在VS2010-VS2015下编译时,如何使用decltype作为较大类型表达式的LHS
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- C++ 雷神库 - 使用资源加载器类时出现问题(不命名类型)
- 模板元程序查找相似的连续类型名称
- 是否可以从int转换为enum类类型
- 构造函数正在调用一个使用当前类类型的函数
- 我应该使用什么来代替void作为变体中的替代类型之一
- 类中的字符串不命名类型