2017-01-15 31 views
4

我正在嘗試尋找一種從我的庫中刪除棄用類的好方法,同時保留出色的錯誤消息。這種想法是基於什麼我已經做功能:如何在保留棄用警告的同時刪除類

namespace 
{ 
    [[deprecated("This function has been replaced by combust()")]] 
    void explode() = delete; // Using variadic templates in reality to have all signatures covered 

    void combust() {} 
} 

int main() 
{ 
    explode(); 
    combust(); 
} 

在鐺,這給了我一個很好的錯誤消息:

<source>:11:2: error: call to deleted function 'explode': This function has been replaced by combust() 
explode(); 
^~~~~~~ 

GCC只給我只能說這個功能已經被刪除的消息。儘管如此,這仍然表明每個人都試圖升級圖書館的意圖,而忽視了貶值警告。

因此,由於這是一個C++庫,我主要有類,並且正在尋找正確的方法來做類似於這些類的事情。我目前的做法是這樣的:

namespace 
{ 
    class [[deprecated("Class has been replaced by Bar")]] Foo 
    { 
     Foo() = delete; // And every other method I had in this class 
    }; 
    class Bar 
    { 
    }; 
} 

int main() 
{ 
    Foo f; 
    Bar b; 
} 

這基本上給了我下面的警告/鐺(和GCC類似的)錯誤:

<source>:13:5: warning: 'Foo' is deprecated: Class has been replaced by Bar [-Wdeprecated-declarations] 
Foo f; 
^ 
<source>:3:60: note: 'Foo' has been explicitly marked deprecated here 
class [[deprecated("Class has been replaced by Bar")]] Foo 
^ 
<source>:13:9: error: call to deleted constructor of '(anonymous namespace)::Foo' 
Foo f; 
^ 
<source>:5:8: note: 'Foo' has been explicitly marked deleted here 
Foo() = delete; 
^ 

我在哪裏可以與功能,因爲這毫無用處代碼活這是單行的,這對類很麻煩,因爲它們可以有很多方法。

那麼,我在尋找,是執行以下操作的一個好辦法:(非編譯代碼)

class [[deprecated("Class has been replaced by Bar")]] Foo = delete; 

封閉我到了一個oneliner是:

struct [[deprecated("Class has been replaced by Bar")]] Foo { Foo() = delete; }; 
struct [[deprecated("Class has been replaced by Bar")]] Foo; 

請注意,不包括Foo通過引用傳遞並調用某些方法的情況。

有沒有人有更好的解決方案來刪除類,同時對以下某些版本有明確的棄用警告?

+1

我認爲您錯誤地使用了您的條款。 「棄用」應該*從不*表示「不起作用」。 [[已棄用]]應該只應用於工作*的方法和類*。棄用是一個標誌,雖然此作品*現在*,它可能會在以後的日期*刪除*。你永遠不應該刪除函數/類,然後標記它們[[已棄用]]。只要刪除它們;編譯器會讓類/函數的用戶知道它們很快就會消失;) –

+0

@NicolBolas如上所述,這是爲忽略棄用警告而輕鬆遷移的第二步。而對於功能,Clang的人相信這是一個好主意,因爲他們甚至有一個特定的錯誤信息來結合這兩者。 – JVApen

+0

「,一些方法被稱爲」 - 如何調用類Foo {Foo()= delete; 「確切地說? – Yakk

回答

1

可以用static_assert來做到這一點,因爲它會導致編譯時錯誤和消息。但是,如果放置在非模板化函數中,它將始終聲明。爲了解決這個問題,我們使它成爲一個模板函數,斷言取決於參數。如果函數未被使用,這不會導致錯誤,因爲它不會被實例化。

template <int I = 0> 
void explode() 
{ 
    static_assert(I && false, "This function has been replaced by combust()"); 
} 

int main() 
{ 
    // error: static_assert failed: "This function has been replaced by combust()" 
    explode(); 
} 

這也可以用於類。但是,由於需要模板參數,因此需要使用typedef。

namespace 
{ 
    template <int I = 0> 
    class FooDeprec 
    { 
     static_assert(I && false, "Class has been replaced by Bar"); 

     FooDeprec() = default; // no need to delete 
    }; 

    using Foo = FooDeprec<>; 
} 

int main() 
{ 
    // error: static_assert failed "Class has been replaced by Bar" 
    Foo f; 
} 

這樣做的好處是不需要太多的改變 - 您可以保留成員函數的聲明。