首页 > 解决方案 > 具有未知类型的 std::conditional

问题描述

我目前正在编写一个使用 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不可用,导致编译失败。

有更好的解决方案吗?

标签: c++c++20std-span

解决方案


好问题!

让我们一步一步来回答

constexpr const bool span_builtin = // ...

这样的事情存在吗?

这行得通吗?

可能不是

https://stackoverflow.com/a/45594334/1691072

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

我们也不能正式将我们自己的跨度转发声明添加到 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)


推荐阅读