std::具有未知类型的条件



我目前正在编写一个使用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(

最新更新