std::conditional 类型未知

std::conditional with unknown type

我目前正在编写一个使用 C++20 的库 std::span。编译器库对 std::span 的支持在这一点上相当稀缺。因此,我有一个允许使用第 3 方实现的 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 不可用时导致编译失败。

有更好的解决方案吗?

问得好!

来回答吧step-by-step

constexpr const bool span_builtin = // ...

有这样的东西吗?

这行得通吗?

可能不会

我们可以使用它,但问题是在 C++20 以下,Span 不会被定义

Also we cannot officially add our own span Forward Declaration to std namespace

那么解决方案是什么?

解决方案最终会与您的解决方案非常相似

#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
}

另见 Proper way to define type (typedef vs #define)