Visual Studio 2017是否完全支持具有[[deprecated]]属性的N4266?

时间:2017-10-11 12:48:30

标签: c++ visual-studio c++17

我目前正在调查C ++ 17的新功能。我偶然发现了功能N4266,它声明现在枚举和名称空间也可以使用属性。不同消息来源称,Visual Studio 2017已经完全支持此功能。我用[[deprecated]]属性编写了一个测试。对于名称空间,这非常有效。但是,没有为枚举生成警告。我的实施中有错误吗?我错过了什么吗?

enum MyEnum
{
    val = 0,
    vaal[[deprecated]] = val
};

void test()
{
    MyEnum e  = MyEnum::vaal; //Should emit Warning, but does not
    MyEnum e2 = MyEnum::val;  //No Warning
}

我正在使用Visual Studio Community 2017版本15.3.5。 This表示自VS2015以来应该支持它。 / std:使用了c ++ 17。

And this也说应该是正确的语法。

如果我使用enum或enum类没有区别。

1 个答案:

答案 0 :(得分:3)

不,不完全。

我想说这是MSVC2017中的当前限制/错误,可能值得提交错误报告,即使该属性也在枚举器情况下被识别(并且没有提示C5030警告;如Mark所述)在你的评论中提问)。

附录:现已通过Hans Passant提供的链接验证(作为先前已知的错误):

C ++ 17(工作草案)标准[decl.attr.deprecated]声明:

  

§1属性标记deprecated可用于标记名称和   仍允许使用的实体,但对某些人不鼓励   原因。

     

§3该属性可以应用于类的声明,a   typedef-name,变量,非静态数据成员,函数,a   名称空间,枚举,枚举器或模板   专业化。 ...

在使用MSVC2017进行编译时使用/std:c++17标志,deprecated属性适用于上述所有内容,但枚举器:

// a class
class [[deprecated]] MyClass {};

// a typedef-name / type alias
[[deprecated]] typedef int MyInt;
using MyFloat [[deprecated]] = float;

// a variable (see main)

// a non-static data member
struct DataMember
{
    int b [[deprecated]];
};

// a function
[[deprecated]]
void myFunction() {}

// a namespace
namespace [[deprecated]] my_namespace
{
    typedef double MyDouble;
}

// an enumeration
enum [[deprecated]] MyEnum {};

// an enumeration
enum MyNewEnum
{
    val[[deprecated]] = 42
};

// a template specialization
template <typename T>
void myTemplateFunction(const T) {} 

template<>
[[deprecated]]
void myTemplateFunction<int>(const int) {}

int main()
{
    MyClass m; // warning C4996: 'MyClass': was declared deprecated
    MyInt i;   // warning C4996: 'MyInt': was declared deprecated
    MyFloat f; // warning C4996: 'MyInt': was declared deprecated
    int j [[deprecated]];
    j = 1;     // warning C4996: 'j': was declared deprecated
    DataMember dm;
    dm.b = 1;  // warning C4996: 'DataMember::b': was declared deprecated
    myFunction();
               // warning C4996: 'myFunction': was declared deprecated
    my_namespace::MyDouble d; 
               // warning C4996: 'my_namespace': was declared deprecated
    MyEnum e;  // warning C4996: 'MyEnum': was declared deprecated
    myTemplateFunction(2);
               // warning C4996: 'myTemplateFunction': was declared deprecated

    MyNewEnum ne = val; // ... no warning

    return 0;
}

对于MyNewEnum ne = val;以及-std=c++14,gcc和clang都会针对上面的-std=c++1z调用弃用警告。

在相关的说明中,特别是cppreference's description of the deprecated attribute似乎没有使用N4266更新,在有效用例声明中不包括“枚举器”和“命名空间”;即使这些都存在于C++14 standard draft (7.6.5/2)中。这可能是一个指示,这是一个很少使用的功能(应用于枚举器/命名空间),这可以解释为什么它(部分)错过了MVCS。

  • 编辑添加了一条关于此的说明,此后又进行了更正。

官方MVSC文档中有些含糊不清

最后,attributes section in the MSVC docs并没有真正深入地指出允许deprecated属性的哪种声明;仅显示弃用函数声明的示例。

尽管如你所指出的那样(但是通过链接到cppreference而不是MSVC自己的文档),MSVS2015 does explicitly state conformance to N4266,至少对于C ++ 17来说。

  

编译器功能

     

C ++ 17核心语言功能

     

N4266名称空间和枚举器的属性

     

支持:VS2015

然而,Support For C++11/14/17 Features (Modern C++)表明相反(对于VS2015):

  

编译器功能

     

C ++ 17提议的核心语言功能

     

N4266名称空间和枚举器的属性

     

支持VS2013:否

     

支持VS2015:否