引用 std::any 或 not_yet_in_std::whatever 的惯用方式是什么?

What's an idiomatic way to refer to either std::whatever or not_yet_in_std::whatever?

本文关键字:std 是什么 方式 yet any not 引用 in whatever      更新时间:2023-10-16

我喜欢跨度,所以我在这里和那里使用gsl::span。但是 - 在 C++20 中,它将改为std::span*。我使用std::optional,但对于 C++14 代码,它需要std::experimental::optional.等等。

在这些变体(有时可能超过两个(之间进行编译时选择的惯用和面向未来的方法是什么,以便我的实际代码只能使用一个编译成正确选择的跨度的标记序列,或可选,或其他类似的结构?

注意:我想避免污染全局命名空间。


* 嗯,从技术上讲,我以后也可以使用gsl::span,但这个问题的想法是一旦标准可用就使用标准中的内容,在此之前使用最近的替代方案。

我通常使用这样的东西:

#if some_kind_of_test_here_not_necessarily_a_macro
namespace stdx = std;
#elif some_other_test_here
namespace stdx = std::experimental;
#else
#error "Some Message"
#endif

现在在你的代码中只需使用:

stdx::span  mySpan;

这个问题是错误的,因为即使有这样的"令牌序列",也不能保证这两种选择的行为相同。

考虑experimental::optionalstd::optional.后者在 C++17 的缺陷报告之后,如果T是微不足道的可复制的,则要求可以平凡复制。experimental::optional不是。如果您依靠它进行 C++17 构建,您不知道它是否会与 C++14 对抗。

gsl::span问题不大,因为GSL实施可能会在std::span被合并到C++20时跟踪对的更改。

但是,如果您坚持这样做,C++20 将使功能测试宏成为强制性的。因此,您可以使用如下宏技术:

#include <version>
#ifdef <insert span test macro here>
#include <span>
template<typename T, std::ptrdiff_t N>
using span = std::span<T, N>;
#else
#include <gsl/span>
template<typename T, std::ptrdiff_t N>
using span = gsl::span<T, N>;
#endif

当然,这里的问题是你必须包含<version>,它本身就是一个 C++20 标头。因此,此代码仅适用于至少部分符合 C++20 的编译器。

一种方法是在迁移命名空间中使用包含合适using别名的迁移标头,例如:

#if __cplusplus < 201402L
#include <experimental/optional>
namespace mig {
template <typename T>
using optional = std::experimental::optional<T>;
}
#else
#include <optional>
namespace mig {
template <typename T>
using optional = std::optional<T>;
}
#endif

在迁移时,您将包含相应的标头,并将mig::optional<T>用于您的代码,该代码使用optional-du-jour 愉快地与其他代码交互。一旦兼容性问题消失,您可以在适当的时候替换您的自定义资格。但是请注意,这些定义之间存在一些差异,即您需要坚持通用功能。

对 @MartinYork 方法的改编,(希望(在单构造级别而不是整个命名空间级别工作:

#if __cplusplus >= 202001L
#include <span>
namespace stdx {
template <class ElementType, std::ptrdiff_t Extent = std::dynamic_extent>
using span = std::span<ElementType, Extent>;
} // namespace stdx
#else
#include <gsl/span>
namespace stdx {
template <class ElementType, std::ptrdiff_t Extent = gsl::dynamic_extent>
using span = std::span<ElementType, Extent>;
} // namespace stdx
#endif // __cplusplus >= 202001L
相关文章: