【问题标题】:How does std::declval<T>() work?std::declval<T>() 如何工作?
【发布时间】:2015-02-16 00:05:53
【问题描述】:

我想了解std::declval&lt;T&gt;() 的工作原理。我知道怎么用,也知道它的作用,主要是让你在不构造对象的情况下使用decltype,比如

decltype(std::declval<Foo>().some_func()) my_type; // no construction of Foo

我从cppreference.com 知道std::declval&lt;Foo&gt;“添加”了对Foo 的右值引用,由于引用折叠规则,它最终成为右值引用或左值引用。我的问题是为什么不调用Foo 的构造函数?如何在不构造模板参数的情况下实现std::declval&lt;T&gt; 的“玩具”版本?

PS:I know和老招不一样

(*(T*)(nullptr))

【问题讨论】:

  • 来自同一页面:“请注意,由于不存在 declval 的定义,因此只能在未计算的上下文中使用它;计算包含此函数的表达式是错误的。”
  • @remyabel 是的,我看到了,我只是不知道如何“构建”我自己的declval
  • template&lt; class T &gt; typename std::add_rvalue_reference&lt;T&gt;::type declval(); 实际上就是您所需要的。 Live example
  • @vsoftco:您正在调用对象的非静态成员函数。 (嗯,如果表达式被评估,你会是)并且为了调用非静态成员函数,你使用一个点。为什么你会期望在这种情况下会有所不同?具体来说,您为什么希望使用范围运算符?

标签: c++ c++11


【解决方案1】:

基本上,在sizeofdecltype 表达式中,您可以调用未在任何地方实现的函数(它们需要声明,而不是实现)。

例如

class Silly { private: Silly( Silly const& ) = delete; };

auto foo() -> Silly&&;

auto main() -> int
{
    sizeof( foo() );
}

链接器不应该抱怨这一点。

【讨论】:

  • 啊,好吧,现在明白为什么“添加右值引用”可以解决问题了。出于某种原因,我不知道您可以在刚刚声明的函数上使用decltype。唯一让我有点疑惑的是,为什么你可以在declval&lt;Foo&gt;().f() 中调用.f(),我原以为你需要declval&lt;Foo&gt;()::f() 之类的东西
  • @vsoft 在未评估的上下文中,所有重要的是类型。你不需要实例来使用实例:你只需要假装。毕竟,如果有两条电车轨道,一只手落在森林里的声音是什么?
  • 我还是不明白。 auto foo() -&gt; Silly; 不也能正常工作吗?还是Silly&amp;?为什么这里需要 r 值引用?
  • @VioletGiraffe 像上面一样,当您不知道模板上下文中手头的类型 T 但需要调用该类型的函数时。你不能写 T().foo(),因为你不能假设 T 有默认(或任何其他)构造函数。因此,您需要通过引用调用函数。我不确定为什么在那里选择右值引用。
  • @Wormer,我迟到了一年,但this 可能会回答为什么在declval() 中使用右值引用。
猜你喜欢
  • 1970-01-01
  • 2016-06-02
  • 2017-12-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多