Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何制作基于变量的链式索引函数?_C++_Arrays_C++11 - Fatal编程技术网

C++ 如何制作基于变量的链式索引函数?

C++ 如何制作基于变量的链式索引函数?,c++,arrays,c++11,C++,Arrays,C++11,如果我有一个对象a,它是一个内置数组或一个具有合适的运算符[]的类类型,并且它返回的类型可以自己索引,那么我应该如何编写一个泛型函数,用一个变量调用而不是用分隔的括号块来索引所有这些对象?换言之,我可以这样表达: a[i0][i1]...[iK] 我想把它写成一个函数: slice( a, i0, i1, ..., iK ) 因为C++规则要求运算符[]/COD>在单个参数上工作,使它与变量无关。(这个问题基于一个Usenet线程,在那里我试着问了一些类似的问题;最后我自己只解决了可能嵌套的

如果我有一个对象
a
,它是一个内置数组或一个具有合适的
运算符[]
的类类型,并且它返回的类型可以自己索引,那么我应该如何编写一个泛型函数,用一个变量调用而不是用分隔的括号块来索引所有这些对象?换言之,我可以这样表达:

a[i0][i1]...[iK]
我想把它写成一个函数:

slice( a, i0, i1, ..., iK )
<>因为C++规则要求<代码>运算符[]/COD>在单个参数上工作,使它与变量无关。(这个问题基于一个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)... );
}
模板
常量表达式
自动切片(T&&T,U&&U)无异常(???)->???
{返回ce_forward(t)[ce_forward(u)];}
模板
常量表达式
自动切片(T&&T、U&&U、V&&V、W.&&W)无例外(???)->???
{
返回片(ce_向前(t)[ce_向前(u)],ce_向前(v),
行政长官(西)…);
}
ce\u forward
函数模板是标记为
std::forward
constepr
。(标准中一些可以标记为
constexpr
的东西没有标记。)我正在尝试找出正确的东西,以放置在返回类型和异常规范点中。我知道的一些案例和注意事项包括:

  • 内置的
    运算符[]
    要求一个操作数是数据指针(或衰减数组引用),另一个是枚举或整数类型。操作数可以是任意顺序。我不知道一个操作数是否可以替换为一个类类型,并将其明确(非显式?)转换为适当的类型
  • 类类型可以将
    运算符[]
    定义为非静态成员函数。任何此类函数只能有一个参数(除此之外)
  • 内置运算符不能抛出。(除非操作数可以基于UDT转换;所述转换是唯一可能的抛出点。)边界错误导致的未定义行为超出了我们的权限
  • 最后一次索引调用返回的是l值引用、r值引用还是值都应该反映在
    切片的返回类型中
  • 如果(final?)调用是按值进行的,那么
    std::is\u nothrow\u move\u constructible::value
    应该根据异常规范执行。(按参考返回值为
    noexcept
  • 如果内置运算符涉及数组,则该步骤返回的引用应为r值引用(如果数组也是一个)。(这是一种缺陷,因为指针与数组不同,失去了目标的l值与r值状态,因此传统的返回总是l值引用。)
  • 对于类类型索引运算符,请确保异常规范和返回类型部分引用的重载与函数体使用的重载相同(如果不止一个)。对于仅在限定
    this
    const
    /
    volatile
    /both/note和/或
    &
    /
    &
    /note)方面有所不同的重载,要小心

要为
slice
函数获取正确的返回值,可以创建一个帮助器模板来计算正确的结果类型。例如:

template <typename T, typename U, typename... V>
struct SliceResult {
    typedef typename SliceResult<T, V...>::Type Type;
};

template <typename T, typename U>
struct SliceResult<T, U> {
    typedef typename std::underlying_type<T[U(0)]>::type Type;
};
模板
结构切片结果{
typedef typename SliceResult::Type Type;
};
模板
结构切片结果{
typedef typename std::底层_type::type type;
};

然后,
slice
函数将返回一个
SliceResult::Type

我根据@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)... );
}
#包括
模板
类索引结果;
模板
类索引结果
{
公众:
使用类型=T;
静态constexpr
bool can_throw=false;
};
模板
类索引结果
{
使用direct_type=decltype(std::declval()[std::declval()]);
使用next_utype=index_uresult;
静态constexpr
bool direct_能_投掷
=不例外(std::declval()[std::declval()]);
公众:
使用type=typename next\u type::type;
静态constexpr
bool can_throw=直接can_throw | | next_type::can_throw;
};
模板
内联常量表达式
自动切片(T&T)无异常->T&&
{返回静态_cast(t);}
模板
内联常量表达式
自动切片(T&&T、U&&U、V&&V)
noexcept(!索引结果::可以抛出)
->typename索引_结果::type
{
返回片(静态施法(t)【静态施法(u)】,
静态铸造(v);
}

我提出了一个要点。它运行在一个运行Gcc>=4.7的网站编译器上,CLAN> 3.2,英特尔C++ > 13。< /P>我使用它的时候,应该尽可能的是<代码> CONTXPROP/COD>。您考虑过简单地将相同的表达式放在<代码>返回< /COD>语句中,对于返回类型和<>代码>除了< /代码>规范之外吗?例如,
noexcept(noexcept(std::declval()[std::declval()])->decltype(std::declval()[std::declval()])
bool direct\u can\u throw=not noexcept(…)
应该在那里吗?@0x499602D2,是的。
noexcept
这个东西想知道我们什么时候不抛出,但是我的类会计算什么时候抛出。哦,是的,我忘记了
not
关键字与
相同:)