【问题标题】:A trick for optional reference using universal references?使用通用引用进行可选引用的技巧?
【发布时间】:2013-03-13 13:36:24
【问题描述】:

我发现了一个在标准 C++11 中使用可选引用的技巧。 您认为这种技术是否可靠并且行为是否根据 C++ 标准定义良好?

// Optional reference using C++11 
// V. Reverdy - 2013
#include <iostream>
#include <type_traits>

template <class T = int, class = typename std::enable_if<std::is_same<typename std::decay<T>::type, int>::value>::type>
void f(T&& n = T())
{
    std::cout<<"--------"<<std::endl;
    std::cout<<"is const = "<<std::is_const<T>::value<<std::endl;
    std::cout<<"is reference = "<<std::is_reference<T>::value<<std::endl;
    std::cout<<"is lvalue reference = "<<std::is_lvalue_reference<T>::value<<std::endl;
    std::cout<<"is rvalue reference = "<<std::is_rvalue_reference<T>::value<<std::endl;
    std::cout<<"--------"<<std::endl;
    n *= 2;
} 

int main(int argc, char* argv[])
{
    int n = 42;
    std::cout<<"n = "<<n<<std::endl;
    f();
    std::cout<<"n = "<<n<<std::endl;
    f(n);
    std::cout<<"n = "<<n<<std::endl;
    return 0;
}

结果是:

n = 42
--------
is const = 0
is reference = 0
is lvalue reference = 0
is rvalue reference = 0
--------
n = 42
--------
is const = 0
is reference = 1
is lvalue reference = 1
is rvalue reference = 0
--------
n = 84

它似乎适用于 liveworkspace 上所有可用的编译器:LWS

【问题讨论】:

  • 你有这方面的实际用例吗?
  • 有趣的是类型类型Tintint&amp;int&amp;&amp;int const&amp; 之间变化,如果您不传入,则会出现int 选项任何事物。我们之所以得到不带参数的int,是因为使用了模板参数的默认值,这意味着不再推导T,并且不再在类型推导上下文中使用T&amp;&amp;...在该函数中尝试std::is_reference&lt;decltype(n)&gt;::value - 您的技术的缺点是T 有时在演绎上下文中,有时不在。

标签: c++ templates c++11 pass-by-reference universal-reference


【解决方案1】:

笏。

首先,您“实现”的目标可以通过重载等方式更简单地实现。其次,它与可选引用完全不同。可选引用是一个值,它可能包含也可能不包含在运行时的引用。行为是明确定义的,但它既不可取也不是可选的参考。将临时引用绑定为默认参数在某些情况下很好,但距离可选引用有十亿英里。

【讨论】:

    【解决方案2】:

    它是明确定义的,是的,因为“通用引用”(请注意这是一个非标准术语)可以解析为右值引用,因此绑定到临时对象,但是你'不创建“可选参考”。

    引用必须始终被初始化并且必须始终绑定到一个对象,它们不能“绑定或不绑定”(这是我对“可选引用”的意思的直观理解)。

    在这里,您只是将该引用绑定到一个临时对象。您所做的相当于以下内容:

    template<typename T> void f(T&& t) { ... }
    void f() { f(int()); }
    

    如果您的意思是说您现在能够创建一个接受引用并且可以在不提供任何参数的情况下调用的函数 - 这是 IMO 更正确的说法 - 那么这是真的,但我不会不要认为这是一个突破性的发现。

    即使在 C++03 中,您也可以执行类似的操作,但仅针对 const 的引用:

    template<typename T>
    void f(T const& = T()) { ... }
    

    由于 C++11 引入了可以绑定到临时对象(右值引用)的非const 引用,因此自然而然地进行了概括,这就是您的技术所利用的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-06
      • 2011-06-21
      • 2010-10-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-19
      • 2023-03-12
      相关资源
      最近更新 更多