如何正确地将功能强制转换为std?

Ged*_*tis 2 c++ std

我最近从Microsoft编译器切换到GCC.在很多事情中,我注意到它std::make_unique变得不可用了.这显然是因为make_unique它不是C++ 11标准的一部分,而且恰好将Microsoft作为扩展包含在内.

我们计划很快转向C++ 14,但同时我写了这个"shim"函数并将其放入std.

namespace std
{
    template<typename T, typename... TArgs>
    unique_ptr<T> make_unique(TArgs&&... args)
    {
        return std::unique_ptr<T>(new T(std::forward<TArgs>(args)...));
    }
}
Run Code Online (Sandbox Code Playgroud)

这解决了gcc上的问题.但是,我认为它会在微软方面引起问题,因为它将是一个重复的定义.

有没有办法将功能正确地填充到std中,这样就不会对不同的编译器/ C++标准造成麻烦?我环顾四周,没有拿出任何东西.对于特定的标准功能,我想也许就像一个包含守卫?

#ifndef MAKE_UNIQUE_DEFINED
#define MAKE_UNIQUE_DEFINED
// Define make_unique
#endif
Run Code Online (Sandbox Code Playgroud)

可悲的是,它似乎std没有定义包含特定功能的警卫.还有什么我可以做的,以使这更正确和编译器/ C++标准不可知?

Sto*_*ica 6

你可以,实际上.只需将帖子中提到的两个条件转换为条件宏定义:

#if defined(_MSC_VER) && __cplusplus == 201103L
#  define MAKE_UNIQUE_DEFINED 1
#endif
Run Code Online (Sandbox Code Playgroud)
  • _MSC_VER检查TU是用MSVC编译的.这是他们预定义的宏之一.您可以使用它来进一步细化检查,因为它是MSVC的编码版本号.
  • 201103L是__cplusplus TU编译为C++ 11时的值(这是跨平台的标准).
  • 如果__cplusplus没有为您正确定义(因为Microsoft),您可以使用_MSVC_LANG宏代替它.

正如您最初计划的那样,上面的内容可用于包裹您的"垫片".或者,或者与这些版本相关的任何其他MSVC扩展,事实上.


作为替代方案,避免重新打开std命名空间(禁止否).您可以使用命名空间将定义显示在安全的位置,并控制程序如何解释它:

namespace extended_std {
  #ifdef MAKE_UNIQUE_DEFINED
    inline namespace
  #else
    namespace
  #endif
  shim {
     // your definition goes here
  }

  #ifndef MAKE_UNIQUE_DEFINED
  using std::make_unique;
  #endif
} 
Run Code Online (Sandbox Code Playgroud)

然后宏只在那里控制extended_std::make_unique所指的内容.它要么创建命名空间inline,要将其内容倾注到封闭的内容中.或者添加一个使用声明std::make_unique.

  • 对不起,我没想到`inline`命名空间.我认为你最好使用`inline namespace`和`namespace`. (2认同)