首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >类型性状`is_noexcept`,`add_noexcept`和`remove_noexcept`?

类型性状`is_noexcept`,`add_noexcept`和`remove_noexcept`?
EN

Stack Overflow用户
提问于 2022-07-30 02:51:26
回答 2查看 167关注 0票数 2

动机:在P0288 std::move_only_function的实现中,我想为从move_only_function<int() noexcept>move_only_function<int()>的转换编写一个不分配的特例。

代码语言:javascript
复制
move_only_function<int() noexcept> f = []() noexcept { return 42; };
move_only_function<int()> g = std::move(f);  // should just copy the bits

我想写,比如,

代码语言:javascript
复制
if constexpr (is_noexcept_version_of<HisSignature, MySignature>::value) { ... }

我想实现这样的类型特性:

代码语言:javascript
复制
template<class, class>
struct is_noexcept_version_of : std::false_type {};

template<class Tp>
struct is_noexcept_version_of<Tp noexcept, Tp> : std::true_type {};

但是没有一个供应商接受这一点;他们都认为Tp noexcept是语法错误。

问:如果不对部分专业进行组合爆炸,即不详尽地研究&&&const等所有可能的组合,你会如何写出这种类型特征?是否可以为is_noexcept_v<T>add_noexcept_t<T>remove_noexcept_t<T>编写简单的封闭类型特征?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-07-30 03:28:07

除了限定转换之外,指针到函数类型之间唯一可能的隐式转换是移除noexcept和类似于指针到成员函数的转换(基到派生转换除外),所以我认为下面的内容应该有效。

代码语言:javascript
复制
struct C {};

template<class A, class B>
struct is_noexcept_version_of : std::bool_constant<
    requires {
       requires std::is_convertible_v<A C::*, B C::*>;
       requires std::is_function_v<A>;
       requires !std::is_same_v<A, B>;
    }> {};
票数 3
EN

Stack Overflow用户

发布于 2022-08-02 19:18:35

你可以通过组合东西来减少组合混乱的长度。

代码语言:javascript
复制
template<class F>
struct function_info;

template<class R, class T, class...Args>
struct function_info<R (T::*)(Args...) const&&>:
  function_helper< R(Args...), class_t<T>, const_v, rvalue_v >
{};
// ^^^^^ combinatorial explosion here ^^^^^
// You have to decompose the type into its independent dimensions, so
// you get 12 (24 if you want to support both methods and functions
// transparently). 

template<class Sig, class T, auto constness, auto refness, auto exceptness >
struct function_helper:
  base_properties<Sig, T, constness, refness, exceptness>
  derived_properties<Sig, T, constness, refness, exceptness>
{};
template<class Sig, class T, auto constness, auto refness, auto exceptness >
using function_helper_t = typename function_helper<Sig, T, consteness, refness, exceptness>::type;


template<class Sig, class T, auto constness, auto refness, auto exceptness>
struct derived_properties {
  using without_const = function_helper_t<Sig, T, no_const_v, refness, exceptness >;
  using with_const = function_helper_t<Sig, T, const_v, refness, exceptness >;
  // ... add/remove each property here.  An add/remove for each dimension.
  // This is the spot that this technique saves on lines
};

template<class Sig, class T, auto constness, auto refness, exceptness >
struct func_type;
// combinatorial explosion here:
template<class R, class...Args, class T>
struct func_type<R(Args...), T, const_v, rvalue_v, noexcept_v> {
  using type = R(T::*) const&& noexcept;
};
// ^^^^^ You have to rebuild the type from the dimensional values, which
// means you get 2 * 3 * 2 = 12 different copy-pastas here ^^^

template<class Sig, class T, auto constness, auto refness, auto exceptness >
struct base_properties:
  func_type<Sig, T, constness, refness, exceptness >
{
  using sig_t = Sig;
  using class_t = T;
  constexpr auto const_v = constness;
  constexpr auto ref_v = refness;
  constexpr auto except_v = exceptness;
};

这至少删除了组合爆炸中的一个层,即假设您想要对一组其他类型(noexcept、const、reference等)做同样的事情。

我们在一个地方分解类型,然后在另一个点重新组合,我们可以重用这些分解/重新组合。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73172543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档