2011-03-30 31 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的依賴關係。