gpt4 book ai didi

c++ - 使用概念禁用类特化

转载 作者:可可西里 更新时间:2023-11-01 17:55:30 24 4
gpt4 key购买 nike

我正在使用 Concepts TS 实现我自己的 std::span 版本。我在执行 these constructors 时卡住了:

template<class Container> constexpr span(Container& cont);
template<class Container> constexpr span(const Container& cont);

备注:这些构造函数不应参与重载决策,除非:

  • Container 不是 span 的特化,并且
  • Container 不是 array
  • 的特化

如何使用概念来实现它?

最佳答案

首先,创建一个特征来检查特化。 arrayspan 在接受类型参数和非类型参数的意义上看起来是一样的:

template <typename T, template <typename, auto> class Z>
struct is_specialization : std::false_type { };
template <typename A, auto V, template <typename, auto> class Z>
struct is_specialization<Z<A,V>, Z> : std::true_type { };

template <typename T, template <typename, auto> class Z>
inline constexpr bool is_specialization_v = is_specialization<T, Z>::value;

然后我们可以从中建立一个概念:

// the last bullet point
template <typename T, typename E>
concept ValidForElement =
ConvertibleTo<std::remove_pointer_t<T>(*)[], E(*)[]>;

template <typename T, typename E>
concept AllowedContainer =
// not a specialization of span (note: requires forward declaration of span)
!is_specialization_v<std::remove_cv_t<T>, std::span>
// not a specialization of array
&& !is_specialization_v<std::remove_cv_t<T>, std::array>
// not a raw array
&& !std::is_array_v<std::remove_cv_t<T>>
&& requires (T cont) {
// data(cont) is well-formed and has a valid type
{ data(cont); } -> ValidForElement<E>
// size(cont) is well-formed
{ size(cont); }
};

你会这样使用:

template <typename Element, std::ptrdiff_t Extent = -1>
struct span {
template <typename C> requires AllowedContainer<C, Element>
span(C&);
template <typename C> requires AllowedContainer<C const, Element>
span(C const&);
};

那里的 const-ness 要求阻止了很好的 partial-concept-id 语法,但我想我们可以为此添加另一个概念:

template <typename T, typename E>
concept ConstAllowedContainer = AllowedContainer<T const, E>;

template <typename Element, std::ptrdiff_t Extent = -1>
struct span {
template <AllowedContainer<E> C> span(C&);
template <ConstAllowedContainer<E> C> span(C const&);
};

不确定这里是否有更聪明的方法。


但实际上这整对构造函数可能是个错误,你想做一个转发引用:

template <typename Element, std::ptrdiff_t Extent = -1>
struct span {
template <AllowedContainer<E> C>
span(C&&);
};

最后一种方法需要对概念进行一些调整(所有 remove_cv_t 都应该变成 remove_cvref_t)。

关于c++ - 使用概念禁用类特化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54221785/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com