gpt4 book ai didi

c++ - 如何制作基于可变参数的链式索引函数?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:36:11 25 4
gpt4 key购买 nike

如果我有一个对象a内置数组或具有合适 operator [] 的类类型,并且它的返回类型本身可以被索引,我应该如何编写一个通用函数来使用可变参数调用而不是单独的括号 block 来索引所有这些类型?换句话说,我可以这样表达:

a[i0][i1]...[iK]

我希望能够将它写成一个函数:

slice( a, i0, i1, ..., iK )

因为 C++ 规则需要 operator []处理单个参数,使其与可变参数的兼容性降低。 (这个问题基于一个 Usenet 线程,我在该线程中尝试提出类似的问题;最终我自己只解决了可能嵌套的内置数组。)

第一次尝试:

template < typename T, typename U >
constexpr
auto slice( T &&t, U &&u ) noexcept(???) -> ???
{ return ce_forward<T>(t)[ ce_forward<U>(u) ]; }

template < typename T, typename U, typename V, typename ...W >
constexpr
auto slice( T &&t, U &&u, V &&v, W... &&w ) noexcept(???) -> ???
{
return slice( ce_forward<T>(t)[ce_forward<U>(u)], ce_forward<V>(v),
ce_forward<W>(w)... );
}

ce_forward函数模板是一个 constexpr -标有std::forward . (标准中可以标记为 constexpr 的某些内容不是。)我正在尝试找出正确的内容以放入返回类型和异常规范点。我知道的一些案例和注意事项是:

  • 内置 operator []要求一个操作数是数据指针(或衰减数组引用),另一个是枚举或整数类型。操作数可以按任意顺序排列。我不知道是否可以将操作数替换为具有明确(非显式?)转换为适当类型的类类型。
  • 类类型可以定义operator []作为非静态成员函数。任何此类函数只能有一个参数(this 除外)。
  • 内置运算符不能抛出。 (除非操作数可以基于 UDT 转换;所述转换是唯一可能的抛出点。)边界错误导致的未定义行为超出了我们的范围。
  • 最后一次索引调用是否返回左值引用、右值引用或值应反射(reflect)在 slice 的返回类型中.
  • 如果(最终?)调用是按值调用,则 std::is_nothrow_move_constructible<ReturnType>::value应该与异常规范进行“或”运算。 (通过引用返回 noexcept 。)
  • 如果内置运算符涉及一个数组,如果数组也是一个数组,则该步骤返回的引用应该是右值引用。 (这是一种缺陷,因为与数组不同,指针失去了其目标的左值与右值状态,因此传统返回将始终是左值引用。)
  • 对于类类型索引运算符,确保异常规范和返回类型部分引用函数体使用的同一个重载(如果超过一个)。警惕仅在 this 的限定上不同的重载( const/volatile/两者/两者都不是和/或 &/&&/两者都不是)。

最佳答案

根据@luc-danton 的评论和@user315052 的回答,我想出了一个解决方案。

#include <utility>

template < typename Base, typename ...Indices >
class indexing_result;

template < typename T >
class indexing_result<T>
{
public:
using type = T;

static constexpr
bool can_throw = false;
};

template < typename T, typename U, typename ...V >
class indexing_result<T, U, V...>
{
using direct_type = decltype( std::declval<T>()[std::declval<U>()] );
using next_type = indexing_result<direct_type, V...>;

static constexpr
bool direct_can_throw
= not noexcept( std::declval<T>()[std::declval<U>()] );

public:
using type = typename next_type::type;

static constexpr
bool can_throw = direct_can_throw || next_type::can_throw;
};

template < typename T >
inline constexpr
auto slice( T &&t ) noexcept -> T &&
{ return static_cast<T &&>(t); }

template < typename T, typename U, typename ...V >
inline constexpr
auto slice( T &&t, U &&u, V &&...v )
noexcept( !indexing_result<T, U, V...>::can_throw )
-> typename indexing_result<T, U, V...>::type
{
return slice( static_cast<T &&>(t)[static_cast<U &&>( u )],
static_cast<V &&>(v)... );
}

我放了一个full example program作为要点。它适用于运行 GCC >= 4.7、CLang >= 3.2 和 Intel C++ >= 13.0 的网站编译器。

关于c++ - 如何制作基于可变参数的链式索引函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10171525/

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