2017-01-15 13 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; 
^ 

これは1ライナーなので、たくさんのメソッドを持つことができるので、クラスにとっては面倒です。

だから、私が探してるものを、次のことを行うための良い方法である:(非コンパイルコード)

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

あなたの規約が間違っていると思います。 「非推奨」とは、「機能していない」という意味ではありません。 [[deprecated]]は、動作するメソッドとクラス*にのみ適用されます。非推奨は、*今すぐ*動作しますが、後で削除される可能性があるという兆候です。関数/クラスを削除してはならず、[[廃止された]]というマークを付けてはなりません。ただ削除してください。コンパイラはクラス/関数のユーザに、彼らがすぐに終了したことを知らせる); –

+0

@NicolBolas説明したように、これは廃止警告を無視するための移行を容易にするための第2のステップである。そして、機能のために、Clangからの人々は、2つを組み合わせるための特定のエラーメッセージを持っているので、良い考えを信じています。 – 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; 
} 

これの利点はあまり変更が必要とされていることである - あなたはメンバ関数の宣言を維持することができます。

関連する問題