我目前正在编写一个使用C++20的std::span
的库。编译器库对std::span
的支持目前还相当匮乏。因此,我有一个marco,它允许使用第三方实现(在我的例子中是tcb::span
(。宏看起来像这样:
#ifdef SPAN_BUILTIN
# include <span>
# define SPAN std::span
#else
# include "3rdparty/span.hpp"
# define SPAN tcb::span
#endif
通过库的使用情况如下:
void my_func(const SPAN<int>& s);
这一点都不好看。我正在寻找一个更好的解决方案,我遇到了std::conditional
,我过去已经使用过它。一个天真的尝试看起来是这样的:
constexpr const bool span_builtin = // ...
template <class T>
using span_type = typename std::conditional<span_builtin, std::span<T>, tcb::span<T>>::type;
这将导致这样的使用:
void my_func(const span_type& s);
问题在于当std::span
不可用时,std::span
在编译时是未知类型,这使得编译失败。
有更好的解决方案吗?
好问题!
让我们逐步回答
constexpr const bool span_builtin = // ...
这样的东西存在吗?
这行得通吗?
可能不是
https://stackoverflow.com/a/45594334/1691072
我们可以使用它,但问题是在C++20以下,跨度不会被定义为
此外,我们不能正式将我们自己的span Forward Declaration添加到std命名空间中
那么解决方案是什么呢?
该解决方案最终将与您的非常相似
#include <type_traits>
#if __cplusplus > 201703L // Do something else for MSVC if you cannot use `/Zc:__cplusplus`
#include <span>
template<typename T, std::size_t N = std::dynamic_extent>
using span = std::span<T, N>;
#else
template<typename T>
using span = tcb::span<T>;
#endif
int main ()
{
#if __cplusplus > 201703L
static_assert(std::is_same_v< span<int>, std::span<int>>);
#else
static_assert(std::is_same_v< span<int>, tcb::span<int>>);
#endif
}
另请参阅定义类型的正确方法(typedef vs#define(