我需要在下一个C ++版本(C ++ 17)中添加的功能。我正在使用MS Visual Studio,它实现了C ++ 11。我希望在几年内我可以升级我的编译工具,因此可以通过标准库获得此功能。
与此同时,我需要手动实现它。我如何定义它以便将来很容易迁移?
我们以std::clamp
为例。
my_clamp
。当我能够使用C ++ 17时,我可以开始使用std::clamp
,并可选择my_clamp
全局替换std::clamp
。这看起来很难看,但可能不会产生任何意外。my::std
中实现它,并执行using namespace my
。这样,我今天就可以开始使用名称std::clamp
,而不会在以后更改它。但是,它是危险/被禁止的吗?clamp
填入std
命名空间。这是UB,但可能会有效。有没有缺点的方法?
是否有接受/习惯的方式这样做?
答案 0 :(得分:2)
在这些情况下我通常做的是:
1.尝试使用最新的C ++编译器和库,它已经包含了我需要的功能/设施
2.失败了(即我被迫使用较旧的C ++标准版本,让我们说C ++ 11,因为旧的工具链),找到一个满足我需要的库。
3.更好的是,如果我需要的东西已经包含在更新的C ++标准或参考实现中,那么#34;库已经存在,我尝试使用参考实现或关闭库,这将减少您的代码中的未来更改
4.熟悉the boost library,因为它很可能已经包含了你需要的内容,它可能是未来C ++标准内容的参考实现。
5.出于上述原因,无论出于何种原因,都要编写自己的实现,但要尽量使其界面与标准提案类似。
对于任何不是来自std :: namespace的内容,请使用namespace aliasing进一步减少将来的更改(切换到更新的工具链和std ::时)。
注1:C ++ 17是当前的C ++标准,下一个应该是C ++ 20 注2:MS VS2017(以及2015年在某种程度上)已经包含了C ++ 17中的部分或大部分内容。
已编辑以包含如何使用命名空间别名的示例
这个例子与C ++文件系统的东西有关,它还没有(更新)使用C ++ 17,但它仍然限于。
它主要依靠预处理器#defines(即HAVE_CXX_EXPERIMENTAL_FILESYSTEM)来启用/禁用所需部分。
我通常使用CMake来检测编译器和库的功能,并以自动方式定义这些宏。
#if _MSC_VER >= 1900 // Microsoft Visual C++ 2015
#define HAVE_CXX_EXPERIMENTAL_FILESYSTEM
#endif
#if defined(HAVE_CXX_EXPERIMENTAL_FILESYSTEM)
// Have Filesystem TS
#include <experimental/filesystem>
namespace filesystem = std::experimental::filesystem;
using std::error_code;
#elif !defined(NO_BOOST)
// Fall-back to Boost.Filesystem library
#include <boost/version.hpp>
#if (BOOST_VERSION >= 103400)
#include <boost/filesystem.hpp>
#else
#include <boost/filesystem/path.hpp>
#include <boost/filesystem/convenience.hpp>
#include <boost/filesystem/exception.hpp>
#endif // (BOOST_VERSION >= 103400)
namespace filesystem = boost::filesystem;
using boost::system::error_code;
// Hack to fix differences with C++17 Filesystem TS
#define copy_options copy_option
#define overwrite_existing overwrite_if_exists
#else
#warning Not implemented
// or #include custom stuff
#endif
以上基本上做的是落空:
1.如果可用,使用和别名命名空间
2.使用boost.filesystem(如果未明确排除NO_BOOST)
3. [可选]如果需要,回退到自定义实现或其他库。
免责声明:此解决方案可能并不完美,但它可以合理地满足我的需求。