2011-03-30 118 views
20

是否可以将枚举值标记为已弃用?C++将枚举值标记为已弃用?

例如

enum MyEnum { 
    firstvalue = 0 
    secondvalue, 
    thirdvalue, // deprecated 
    fourthvalue 
}; 

二等奖解决方案是ifdef MSVC和GCC解决方案。

+3

你有什么要发生?只需重新命名它,编译器将发出错误... – Lindydancer 2011-03-30 15:00:26

+3

@Lindydancer:但是这不仅仅是贬抑,不是吗?我认为重点在于允许现有代码进行编译,但发出有关已弃用资源的警告。 – 2011-03-30 15:07:53

+7

@Lindydancer:它已经足够了,不需要对类,函数,类型进行弃用... – moala 2011-03-30 15:08:31

回答

1

使用编译器相关编译指示:以下是GccVisual Studio的文档。

+3

这并不真正回答这个问题,例如, gcc允许将函数,类型和变量标记为“已弃用”,但没有提及将其应用于特定的枚举值。 – 2011-03-30 15:09:22

+2

不幸的是,gcc不允许你指定一个属性到一个枚举值,只在整个枚举类型上。你当然可以创建两个枚举(一个带有不赞成使用的值)作为解决方法,但当然它们会有不同的类型。 – Damon 2011-03-30 15:13:14

+0

@Damon:也许有一个参考,那将是一个很好的答案。 – moala 2011-03-30 15:15:41

1

你可能可以使用一些宏hackery。

enum MyEnum { 
    firstvalue = 0 
    secondvalue, 
    real_thirdvalue, // deprecated 
    fourthvalue 
}; 

template <MyEnum v> 
struct real_value 
{ 
    static MyEnum value() 
    { 
     1 != 2U; // Cause a warning in for example g++. Leave a comment behind for the user to translate this warning into "thirdvalue is deprecated" 
     return v; 
    } 
}; 

#define thirdvalue (real_value<real_thirdvalue>::value()); 

当需要一个常数时,这在上下文中不起作用。曾经使用的变量时

enum MyEnum { 
    firstvalue = 0, 
    secondvalue, 
    thirdvalue, // deprecated 
    fourthvalue 
}; 
#pragma deprecated(thirdvalue) 

然后,编译器将输出如下:

+0

我不知道这是否有效,但为纯粹血腥头脑的hackery +1。 ;-) – 2011-03-30 15:42:40

+0

你为什么要这样疯狂? – lpapp 2013-11-29 06:00:48

13

你能做到这一点

warning C4995: 'thirdvalue': name was marked as #pragma deprecated 

编辑
这看起来有点哈克和我没有一个GCC编译器来确认(有人可以为我做这件事?)但它应该工作:

enum MyEnum { 
    firstvalue = 0, 
    secondvalue, 
#ifdef _MSC_VER 
    thirdvalue, 
#endif 
    fourthvalue = secondvalue + 2 
}; 

#ifdef __GNUC__ 
__attribute__ ((deprecated)) const MyEnum thirdvalue = MyEnum(secondvalue + 1); 
#elif defined _MSC_VER 
#pragma deprecated(thirdvalue) 
#endif 

这是我的答案和MSalters的回答

+0

你知道是否有可能使它更好?没有“in-between”#ifdef _MSC_VER?我正在尝试编写一个宏来处理它跨平台的问题,但这让最终用户感到更加不愉快。如果最终用户可以使用独立的宏,那将会很好。 – lpapp 2013-11-28 12:36:51

+0

还有一点,如果没有ifdef,它可能会破坏基于给定平台上基础枚举表示的二进制兼容性。 – lpapp 2013-12-03 17:00:43

3

井的组合,因为我们在宏观黑客已经,这里是我的:-)

enum MyEnum 
{ 
foo, 
bar, 
baz 
}; 

typedef __attribute__ ((deprecated))MyEnum MyEnum_deprecated; 
#define bar ((MyEnum_deprecated) bar) 

int main() 
{ 
    int a = foo; // yuck, why did C++ ever allow that... 
    int b = bar; 

    MyEnum c = foo; 
    MyEnum d = bar; 

    return 0; 
} 

这个工程用gcc,它也不要求你打破型号安全。不幸的是它仍然用宏来滥用你的代码,所以。但据我所知,这是一样好。

Tom提出的建议更清洁(我认为适用于MSVC),但不幸的是gcc会给你的唯一信息是“忽略编译指示”。

+0

它现在可以工作:P – Tom 2011-03-31 15:38:07

+0

这可以在类或名称空间内使用枚举吗? – lpapp 2013-11-28 12:46:28

+0

由于这是一个宏观黑客,它将会与名称空间内的枚举“工作”,甚至比您希望的更好。这是宏的缺点,它们仅仅取代文本而不尊重命名空间。不幸的是,你不能将一个属性分配给一个枚举器,而只能分配给完整的东西。所以你必须做这样的黑客才能使它工作。 – Damon 2013-11-28 14:03:04

3

可以enum声明外声明枚举常量:

enum MyEnum { 
    firstvalue = 0 
    secondvalue, 
    thirdvalue 
}; 
__attribute__ ((deprecated)) const MyEnum fourthvalue = MyEnum(thirdvalue + 1); 
+0

虽然这不适用于msvc,也不适用于C++ 11类枚举。 – lpapp 2013-11-29 06:07:04

+0

如果编译器为MyEnum选择了一个不足以容纳您赋值的值('thirdvalue + 1'),它也会中断。 – 2014-07-10 08:54:53

0

我有一个解决方案(马克B的启发),使得使用升压/系列化/ static_warning.hpp的。但是,我允许thirdvalue用作符号常量。它还会为有人试图使用thirdvalue的每个地方发出警告。

#include <boost/serialization/static_warning.hpp> 

enum MyEnum { 
    firstvalue = 0, 
    secondvalue, 
    deprecated_thirdvalue, // deprecated 
    fourthvalue 
}; 

template <int line> 
struct Deprecated 
{ 
    BOOST_SERIALIZATION_BSW(false, line); 
    enum {MyEnum_thirdvalue = deprecated_thirdvalue}; 
}; 

#define thirdvalue (static_cast<MyEnum>(Deprecated<__LINE__>::MyEnum_thirdvalue)) 

enum {symbolic_constant = thirdvalue}; 

int main() 
{ 
    MyEnum e = thirdvalue; 
} 

海合会我得到的最终指向包含thirdvalue罪魁祸首线警告。

请注意,使用Deprecated模板可以使“实例化到此处”的编译器输出行显示废弃枚举的使用位置。

如果您可以找出在Deprecated模板中可移植生成警告的方法,那么您可以取消对Boost的依赖关系。