如果我有a
一个内置数组或具有合适的类类型的对象operator []
,并且它的返回类型可以自己索引,我应该如何编写一个通用函数,可以通过可变参数调用而不是分隔来索引所有这些对象括号块?换句话说,我可以表达如下:
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 转换;所述转换是唯一可能的抛出点。)由边界错误引起的未定义行为超出了我们的权限范围。
- 最后一次索引调用是否返回左值引用、右值引用或值应该反映在
slice
. - 如果(最终?)调用是按值调用,那么
std::is_nothrow_move_constructible<ReturnType>::value
应该对异常规范进行 OR'd。(按引用返回是noexcept
。) - 如果内置运算符涉及一个数组,则该步骤的返回引用应该是一个右值引用,如果该数组也是一个。(这是一种缺陷,因为与数组不同,指针会丢失其目标的左值与右值状态,因此传统的返回始终是左值引用。)
- 对于类类型索引运算符,请确保 exception-spec 和 return-type 部分引用函数体使用的相同重载(如果不止一个)。
this
请注意仅在(const
/volatile
/both/neither 和/或&
/&&
/neither)的限定方面不同的重载。