2017-01-15 33 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; 
} 

这样做的好处是不需要太多的改变 - 您可以保留成员函数的声明。