简体   繁体   中英

“using” (or other mechanism) to swap in unique_ptr for auto_ptr in C++11?

I'm catching a compile warning under Cygwin with -std=c++11 :

cryptlib.cpp: In member function ‘virtual size_t PK_Signer::SignMessage(RandomNumberGenerator&, const byte*, size_t, byte*) const’:
cryptlib.cpp:770:41: warning: ‘auto_ptr’ is deprecated (declared at /usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
std::auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));
                                       ^

I tried adding:

#if defined(MYLIB_CXX11)
using auto_ptr = std::unique_ptr;
#else
using std::auto_ptr;
#endif

auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));

But it resulted in the following, even with <memory> included.

$ make cryptlib.o 
c++ -std=c++11 -DNDEBUG -g2 -O3 -fPIC -march=native -DCRYPTOPP_DISABLE_ASM -Wall -Wextra -pipe -c cryptlib.cpp
cryptlib.cpp:770:27: error: no type named 'unique_ptr' in namespace 'std'
    using auto_ptr = std::unique_ptr;
                     ~~~~~^

I also tried variations of the following:

#if defined(MYLIB_CXX11)
typedef std::unique_ptr<T> local_ptr<T>;
#else
typedef std::auto_ptr local_ptr;
#endif

I can't make a clean cut-over to unique_ptr because its a C++03 library, and C++03 lacks unique_ptr . And I can't allow the dirty compile to continue under C++11 because clean compiles are a security gate, and governance will not allow the library to pass. (And warning tricks are out of the question because this is should be simple, low hanging fruit. Warning tricks include disabling the warning).

Is it possible to use " using " to swap in unique_ptr ? Or is there some other mechanism?

I tried adding:

using auto_ptr = std::unique_ptr;
using std::auto_ptr;
auto_ptr<PK_MessageAccumulator> m(NewSignatureAccumulator(rng));

But it resulted in the following, even with included.

cryptlib.cpp:770:27: error: no type named 'unique_ptr' in namespace 'std'

That's because std::unique_ptr is a template , not a type. Instead, this should work

#if __cplusplus >= 201103L
  // with C++11 we have std::unique_ptr (and std::auto_ptr is deprecated)
  template<typename T>
  using auto_ptr = std::unique_ptr<T>;
#else
  // assuming C++03 when there is std::auto_ptr
  using std::auto_ptr;
#endif

(requires that you use merely auto_ptr in your code, rather than std::auto_ptr ).


Of course, I am assuming that you use a valid C++ compiler and standard library . On Mac OS, you can use (you may need to install Xcode and command-line tools)

/usr/bin/c++ -std=c++11 -stdlib=libc++

which invokes the clang C++ compiler and the clang C++ standard library.

Understanding that the code is under your control and can be recompiled with or with out C++11 support, an alias can be created for the smart pointer required (either std::unique_ptr or std::auto_ptr ).

template <typename T>
struct local_ptr {
    #if defined(MYLIB_CXX11)
    typedef std::unique_ptr<T> ptr;
    #else
    typedef std::auto_ptr<T> ptr;
    #endif
};

Then used in the client code as such;

local_ptr< PK_MessageAccumulator>::ptr managed = //...

The syntax is more awkward than desired, but this is to accommodate the requirement to support C++03.

In all cases, the long term solution is to factor out the use of auto_ptr or silence the deprecated warnings.

You have two options.

  • Use auto_ptr in your application, and leave the library as it is. Deprecation warnings will not prevent the application from working correctly, they are only there to help.

  • Use unique_ptr in your application, and modify the library to use unique_ptr as well.

You can't mix them. If you can't modify the library, then you will be forced to use auto_ptr in your code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM