【问题标题】:Expressing the result type of the ternary conditional `?:`表示三元条件`?:`的结果类型
【发布时间】:2015-02-05 16:44:21
【问题描述】:

你为下面的函数指定什么返回类型,它应该像?:但没有懒惰?

我的第一次尝试如下:

template <typename T1, typename T2>
T1 myif(bool b, T1&& true_result, T2&& false_result)
{
    if (b) {
        return true_result;
    } else {
        return false_result;
    }
}

但后来我发现:

int f() { return 42; }
int x = 5;

同时

(true ? x : f())++; 

编译失败,

myif(true, x, f())++;

编译正常并返回一个悬空引用。

我的第二次尝试是将返回类型更改为:

typename std::remove_reference<T1>::type

然后

(true ? x : x)++

有效,但是:

myif(true, x, x)++

没有,因为我现在按价值返回。

偶数:

auto myif(bool b, T1&& true_result, T2&& false_result) 
  -> typeof(b ? true_result : false_result)

失败,我不知道为什么,也许typeof 将它的参数转换为值类型。无论如何,重点是明确地表达类型,而不是通过autotypeof

知道如何创建一个返回与?: 相同类型的函数吗?

【问题讨论】:

  • std::common_type,但这不会保留值类别,因为结果是std::decay'd。此外,C++11 的拼写是 decltype,而不是 typeof
  • 为什么不decltype(b ? std::forward&lt;T1&gt;(true_result) : std::forward&lt;T2&gt;(false_result))
  • 反正?:的规则占标准的1.5页。它的某些部分需要知道 AFAIK 无法以编程方式确定的事情(例如,表达式是否可以转换为 T&amp;T&amp;&amp;受引用必须直接绑定的约束);如果没有decltype(例如,通常的算术转换),其他方法也可以实现,但非常繁琐。
  • 如果您需要 C++03 兼容性,您可能想查找这个:stackoverflow.com/a/2450157/34509

标签: c++ templates c++11 c++14


【解决方案1】:

我认为最好的方法是Casey 提出的:

template <typename T1, typename T2> 
auto myif(bool b, T1&& true_result, T2&& false_result)
    -> decltype(b ? std::forward<T1>(true_result) : std::forward<T2>(false_result))
{
    if (b) {
        return true_result;
    } else {
        return false_result;
    }   
}

这在 C++14 中变成了:

template <typename T1, typename T2> 
decltype(auto) myif(bool b, T1&& true_result, T2&& false_result)
{
    // same body
}

鉴于:

int f() { return 42; }
int x = 5, y = 7;

myif(true, x, f())++; // error: lvalue required as increment operand
myif(false, x, y)++;  // OK

【讨论】:

  • 如果类型不同,它是否真正编译过? bool 不是编译时间常数,所以编译器如何知道结果应该是什么类型,除非它们开始的类型相同......?
  • @user673679 当然可以。只要有一个共同的类型(例如,你不能像b ? "hello" : 4.2 那样做)。有关详细说明,请参阅reference
  • 谢谢。我想我之前并没有真正考虑过这样的三元运算符。
  • 您的 C++14 版本已损坏。 “如果一个声明的返回类型包含占位符类型的函数有多个返回语句,则为每个返回语句推导返回类型。如果每个推导中推导的类型不相同,则程序格式错误。”
  • 如果类型相同,两个版本都会损坏。如果T1T2 都是int,那么在C++11 版本中,返回类型被声明为int &amp;&amp;。在 C++14 版本中,decltype(auto) 导致返回类型被推断为int &amp;&amp;。无论哪种方式,true_resultfalse_result 都是无法绑定到右值引用的左值。
猜你喜欢
  • 1970-01-01
  • 2017-11-16
  • 2017-07-12
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 2019-01-22
相关资源
最近更新 更多