【问题标题】:How can an array work with the conditional operator?数组如何与条件运算符一起使用?
【发布时间】:2013-04-21 04:47:15
【问题描述】:

这是对my previous post 的复述,因为我更改了问题(因此它可能没有被标记为新问题而被遗漏)。我也希望能把它剪掉。

我有这样的功能:

#include <cstddef>
#include <type_traits>

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

template < typename E, typename T, std::size_t N, typename U, typename ...V >
inline constexpr
auto  checked_slice( E &&e, T (&t)[N], U &&u, V &&...v )
 -> typename remove_some_extents<T, sizeof...(V)>::type &
{
    typedef typename std::remove_reference<U>::type                 u_type;
    typedef typename std::common_type<u_type, std::size_t>::type  cmp_type;

    return ( u < u_type{} ) || ( static_cast<cmp_type>(u) >=
     static_cast<cmp_type>(N) ) ? throw e : checked_slice( static_cast<E &&>(e),
     t[static_cast<U &&>( u )], static_cast<V &&>(v)... );
}

其中remove_some_extents 是一个自定义类模板,就像调用std::remove_extent 元函数给定次数一样。

当我尝试运行该程序时,我遇到了一堆错误,例如:“来自Whatever(*)[Y] 类型的表达式的Whatever(&amp;)[X][Y] 类型的引用无效初始化”(或Whatever(&amp;)[Z] 来自Whatever*)。我的解决方法是将条件表达式转换为 if-else 对(并删除 constexpr)。

我正在尝试找出问题所在,因此我正在浏览有关 C++ (2011) 标准中条件运算符的部分。这是第 5.16 节。当两个可能的操作之一是 throw 命令(或者是 void 表达式)时,条件具有另一个表达式的类型,但标准转换,包括数组到指针,适用于另一个表达。 (这在第 2 段中。)我认为这让我感到困惑。有什么办法吗?我认为返回数组引用会抑制 a-p 转换。为什么做成if/else会起作用?

【问题讨论】:

    标签: c++ arrays c++11 conditional-operator throw


    【解决方案1】:

    您的分析是正确的。我怀疑非void 操作数在这种情况下“衰减”(即执行通常的转换),以便模仿两个操作数类型不同时发生的情况——在后一种情况下,比不是整个条件表达式都是纯右值。

    我们确定条件表达式的值类别和类型的一种情况是两个操作数完全匹配时,因此我们可以利用它来发挥我们的优势:

    cond ? (throw e, t) : t
    

    将是数组引用类型的左值。 (当然最后一个操作数不必是字面意义上的t——你可以在这里插入你的递归调用。)

    您在使用if/else 时没有遇到任何此类障碍,因为作为语句,该语言不必为其指定通用类型和值类别。

    【讨论】:

    • 从编译器网页的测试中,您不需要括号! ?: 的语法是 LOGICAL_OR_EXPR ? EXPR : ASSIGN_EXPR。第三部分可以是除逗号运算符之外的任何内容。第二部分没有有这个限制! (第 1 部分的优先级高于 ?:。)
    • 括号很少有利于编译器。
    • 答案有效。你可以看到 the code 提交 SHA 66ca088332dd1e57fdaf9e90749105224c301afb,第 136 行到第 159 行。
    猜你喜欢
    • 2016-06-28
    • 1970-01-01
    • 2020-04-22
    • 1970-01-01
    • 2020-04-15
    • 2014-08-21
    • 1970-01-01
    • 2011-02-22
    • 2020-01-29
    相关资源
    最近更新 更多