2013-04-26 51 views
3

这是一个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(&)[X][Y]类型的参考无效初始化”(或Whatever(&)[Z]Whatever*)。我的解决方法是将条件表达式转换为if - else对(并删除constexpr)。

我想弄清楚什么是错的,所以我在C++(2011)标准中讨论有关条件运算符的部分。这是第5.16节。当两个可能的操作之一是throw命令(或者是其他的void表达式)时,那么该条件具有另一个表达式的类型,但是标准转换(包括数组到指针)应用于该另一个表达式。 (这是在第2段。)我认为这就是搞砸了我。有没有办法解决它?我认为返回数组引用会抑制a-to-p转换。为什么它在制作成if/else时工作?

回答

4

你的分析是正确的。我怀疑在这种情况下,非void操作数是“衰减的”(也就是执行通常的转换),以便模拟两种操作数在类型上有所不同时发生的情况 - 后者通常不是整个条件表达式是一个前值。

中,我们知道肯定值类别和条件表达式是当两个操作数完全匹配,因此我们可以使用的类型两者的一种情况是我们的优势:

cond ? (throw e, t) : t 

将是一个左值数组引用类型。 (当然,最后的操作并不一定是字面上t - 你可以将你的递归调用在这里就好了。)

使用if/else时,您没有遇到任何障碍等,因为作为语言做了发言不必为它指定一个通用的类型和值类别。

+0

从在编译器网页上进行测试,您不需要括号! '?:'的语法是'LOGICAL_OR_EXPR? EXPR:ASSIGN_EXPR'。第三部分可以是除逗号操作符之外的任何内容。第二节不*有这种限制! (第一部分是比'?:'更高优先级的任何东西。) – CTMacUser 2013-04-27 10:56:27

+0

括号对于编译器来说很少有用。 – 2013-04-27 11:08:39

+0

答案奏效。你可以看到[代码](https://github.com/CTMacUser/ArrayMD/blob/master/include/boost/utility/slice.hpp),提交SHA 66ca088332dd1e57fdaf9e90749105224c301afb,行136到159。 – CTMacUser 2013-04-27 12:27:54

相关问题