Search code examples
g++c++14typedefdeprecation-warningusing-declaration

[[deprecated]] incompatible with using but compatible with typedef


I discovered (with g++ 6.3) that I can use the [[deprecated]] attribute to deprecate a typedef ([[deprecated]] typedef longname shortname;) but not a using declaration ([[deprecated]] shortname = longname;).

So I was wondering, is this intended (if yes, why?)? Or is this a bug?

This as a MWE:

#include <vector>

namespace our { 
  using vector = std::vector<float>;
} 

//[[deprecated("use the namespace 'our'")]] using myvector = std::vector<float>;
[[deprecated("use the namespace 'our'")]] typedef std::vector<float> myvector;

int main() { 
  myvector a;
  return a.size();
} 

gives depending on which of the lines is commented in the following warning (intended):

g++  -march=native -std=c++11 -m64 -O2 -g -Wextra -Wall -Wshadow -lstdc++ -m64 -g -march=native -flto  main.cpp   -o main
main.cpp: In function ‘int main()’:
main.cpp:11:12: warning: ‘myvector’ is deprecated: use the namespace 'our' [-Wdeprecated-declarations]
   myvector a;
            ^
main.cpp:8:70: note: declared here
 [[deprecated("use the namespace 'our'")]] typedef std::vector<float> myvector;
                                                                      ^~~~~~~~

or the following error (unintended)

g++  -march=native -std=c++11 -m64 -O2 -g -Wextra -Wall -Wshadow -lstdc++ -m64 -g -march=native -flto  main.cpp   -o main
main.cpp:7:43: error: expected unqualified-id before ‘using’
 [[deprecated("use the namespace 'our'")]] using myvector = std::vector<float>;
                                           ^~~~~
main.cpp: In function ‘int main()’:
main.cpp:11:3: error: ‘myvector’ was not declared in this scope
   myvector a;
   ^~~~~~~~
main.cpp:12:10: error: ‘a’ was not declared in this scope
   return a.size();
          ^

Solution

  • The [[deprecated]] statement can not be placed at that position in the using statement (though I think in the line before would be nice).

    Out of these

    //using [[deprecated("use the namespace 'our'")]] myvector = std::vector<float>;
    using myvector [[deprecated("use the namespace 'our'")]] = std::vector<float>;
    //using myvector = [[deprecated("use the namespace 'our'")]] std::vector<float>;
    //[[deprecated("use the namespace 'our'")]] typedef std::vector<float> myvector;
    

    The first won't compile, clang gives a nicer error message in this case

    clang++ -Weverything -std=c++14 -O2 -g main.cpp   -o main
    main.cpp:4:18: warning: alias declarations are incompatible with C++98 [-Wc++98-compat]
      using vector = std::vector<float>;
                     ^
    main.cpp:7:11: warning: C++11 attribute syntax is incompatible with C++98 [-Wc++98-compat]
        using [[deprecated("use the namespace 'our'")]] myvector = std::vector<float>;
              ^
    main.cpp:7:11: error: an attribute list cannot appear here
        using [[deprecated("use the namespace 'our'")]] myvector = std::vector<float>;
              ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                                                 [[deprecated("use the namespace 'our'")]]
    main.cpp:7:64: warning: alias declarations are incompatible with C++98 [-Wc++98-compat]
        using [[deprecated("use the namespace 'our'")]] myvector = std::vector<float>;
                                                                   ^
    main.cpp:13:3: warning: 'myvector' is deprecated: use the namespace 'our' [-Wdeprecated-declarations]
      myvector a;
      ^
    main.cpp:7:53: note: 'myvector' has been explicitly marked deprecated here
        using [[deprecated("use the namespace 'our'")]] myvector = std::vector<float>;
                                                        ^
    main.cpp:14:10: warning: implicit conversion loses integer precision: 'size_type' (aka 'unsigned long') to
          'int' [-Wshorten-64-to-32]
      return a.size();
      ~~~~~~ ^~~~~~~~
    5 warnings and 1 error generated.
    

    So this points out that the attribute is "just in the wrong place" (and interestingly the deprecation warning gets later still printed as desired!)

    The third prints a warning for gcc (though not what we want) warning: ignoring attributes applied to class type ‘std::vector<float>’ outside of definition [-Wattributes] or and error for clang 'deprecated' attribute cannot be applied to types.

    The second is what we want.