如果我有一个对象a,无论是内置数组还是具有合适类的类型operator [],并且其返回类型都可以自己编入索引,我应该如何编写一个泛型函数,该函数可以使用可变参数调用而不是分离来索引所有这些函数支架块?换句话说,我可以制作如下表达式:
a[i0][i1]...[iK]
Run Code Online (Sandbox Code Playgroud)
我希望能够将其作为单个函数编写:
slice( a, i0, i1, ..., iK )
Run Code Online (Sandbox Code Playgroud)
因为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)... );
}
Run Code Online (Sandbox Code Playgroud)
该ce_forward函数模板是一个constexpr-marked std::forward.(标准中可以标记的一些东西constexpr不是.)我正在试图找出正确的东西放入返回类型和异常规范点.我知道的一些案例和警告是:
operator []需要一个操作数作为数据指针(或衰减数组引用),另一个操作数是枚举或整数类型.操作数可以按任意顺序排列.我不知道操作数是否可以用具有明确(非显式?)转换为适当类型的类类型替换.operator []为非静态成员函数.任何这样的函数只能有一个参数(除此之外this).slice.std::is_nothrow_move_constructible<ReturnType>::value应该对异常规范进行OR运算.(按参考回报是noexcept.)this(const/ volatile/ both/both和/或&/ &&/ both)的资格不同的重载.我根据@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)... );
}
Run Code Online (Sandbox Code Playgroud)
我把一个完整的示例程序作为要点。它可以在运行 GCC >= 4.7、CLang >= 3.2 和 Intel C++ >= 13.0 的网站编译器上运行。
| 归档时间: |
|
| 查看次数: |
348 次 |
| 最近记录: |