引用 std::any 或 not_yet_in_std::whatever 的惯用方式是什么?
What's an idiomatic way to refer to either std::whatever or not_yet_in_std::whatever?
我喜欢跨度,所以我在这里和那里使用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::optional
与std::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
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- "using namespace std;"在C++的作用是什么?
- "std::unique_XXX"命名约定背后的基本原理是什么?
- 如果 KEY 是 std::list 或 std::vector 而不是值,那么 std::map 的默认行为是什么?
- 当为可变性配置时,boost::heap::d_ary_heap 保留的额外 std::list 的目的是什么?
- 引用 std::any 或 not_yet_in_std::whatever 的惯用方式是什么?
- 在自定义 std::vector-like 容器中处理指针和非指针模板类型的最佳方法是什么?
- 在 C# 中等效的 std::rotate() 是什么?
- MyType 允许 std::atomic 的确切要求是什么<MyType>?
- std::minstd_rand的界限是什么?
- 向后迭代 std::array 或 std::vector 的正确方法是什么?
- std::set<Key,Compare,Allocator>::find() 函数使用"<"运算符而不是"=="运算符背后的直觉是什么?
- 通过作为指向 C++ 函数的指针传递来访问 std::array 元素的正确方法是什么?
- 创建可以遍历 std::map 值的通用模板迭代器的最简单方法是什么?
- 这句话是什么意思 - " vector<long long> distance(n, std::numeric_limits<long long>::max()); "?
- 在 std::visit 中跳过变体类型的一些重载组合的方法是什么?
- 最接近"std::atomic<std::vector>"是什么?
- std::make_array的目的是什么?C++20 还需要吗?
- 将(临时的?)std::string传递给使用它来构造一个接受副本的对象的函数的最佳方法是什么?
- C++20 std::common_reference的目的是什么?