GCC 4.7 的可选和变体

optional and variant with gcc 4.7

本文关键字:GCC      更新时间:2023-10-16

我有代码应该用gcc 4.7编译, 它有不错的 C++11 支持,但缺少 C++14 和 C++17。

我想在我的代码中使用std::optionalstd::variant, 具有boost::optional的回退和 GCC 4.7 的boost::variant

实现这一目标的标准方法是什么?

我看到两种变体:

  1. 包装变体,它可能是宏的,例如:#define VARIANT_TYPE boost::variantnamespace my_code { using variant = boost::variant }
  2. 扩展std命名空间

第一个不好,因为我的代码会用my_code::variant, 而不是std::variant.第二个对我来说看起来更清楚。

一般情况下,2可能是 UB,扩展 std 命名空间被视为未定义行为的原因是什么?

但是我的具体情况呢?我知道gcc的确切版本variant/optional,我可以在构建的配置阶段进行检查。对于所有其他编译器/标准 c++ 库,我可以要求 c++17 支持,而不是使用将boost::optional转换为std::optional的技巧。

我还能发现一些奇特的问题吗?

你可以使用类似的东西:

#ifdef NEED_WORKAROUND
# include <boost/optional.hpp>
# include <boost/variant.hpp>
namespace workaround
{
namespace std
{
using boost::optional;
using boost::variant;
}
}
using namespace workaround;
#else
# include <optional>
# include <variant>
#endif

因此,与::std::variant<..>
一起使用不起作用,但简单的std::variant<..>大多表现相似(您可能会遇到 ADL 问题)。

接近你想要的一种方法是找到一个适合你的库。

例如,谷歌的Abseil就是这样做的。不幸的是,他们的支持平台页面显示他们需要 gcc 4.8+,因为他们需要 C++11。但如果能满足他们的要求,那么可以用absl::optional代替std::optional,如果std::optional存在,那么absl::optional就是std::optional,否则就等同于std::optional

你写absl::optional而不是std::optional是无关紧要的;你的代码库的读者可以很容易地知道它们是"一回事"。我强烈建议不要尝试将其放入std命名空间中。


自己这样做是不愉快的,但并非不可能。您需要两样东西:

  • 判断std::optional是否存在的方法
  • 另一个命名空间中实现std::optional,该命名空间适用于要支持的编译器版本(请注意,boost版本不一定与std版本完全等效)

然后,您可以像选项 1 中一样编写解决方法,并编写类似以下内容的内容:

#if STD_OPTIONAL_EXISTS
namespace compat {
template <typename... Ts>
using optional = std::optional<Ts...>;
}
#else
namespace compat {
template <typename... Ts>
using optional = boost::optional<Ts...>;
}
#endif
相关文章:
  • 没有找到相关文章