【问题标题】:How to obtain a const qualified declval?如何获得 const 合格的 declval?
【发布时间】:2014-01-13 20:48:45
【问题描述】:

考虑以下代码:

#include <iostream>
#include <type_traits>
#include <typeinfo>

struct Base
{
    int f() const;
    double f();
};

struct Derived
: public Base
{
    template <typename T = decltype(std::declval<Derived>().f())> // Modify this
    T g() const;
};

int main()
{
    const Derived x;
    std::cout<<typeid(decltype(x.g())).name()<<std::endl; // Prints "d", not "i"
    return 0;
}

如何修改decltype(std::declval&lt;Derived&gt;().f()) 使其返回int 而不是double

我尝试过decltype(std::declval&lt;const Derived&gt;().f(),但它无法编译。

【问题讨论】:

    标签: c++ c++11 constants decltype


    【解决方案1】:

    GCC 4.8.1 喜欢这个:

    template <typename T = decltype(std::declval<Base const>().f())> 
    

    你需要告诉编译器你调用的对象是const

    您不能在此declval 中指定Derived,因为在调用时,Derived 是不完整的类型。此外,您甚至不需要将Derived 作为declval 的一部分,因为f()Base 的成员。

    【讨论】:

    • 您已将 Derived 更改为 Base。为什么?
    • @0x499602D2:因为在调用时,Derived 是一个不完整的类型。它也不需要,因为调用实际上是在Base
    【解决方案2】:

    您正在尝试在需要完整的上下文中使用Derived,但它还不能完整,因为它是完成定义所需的方法返回类型的一部分。编译器无法解决此循环。

    您需要使用带有std::declval&lt;const Base&gt;() 的基类,您的代码才能编译。

    【讨论】:

      【解决方案3】:

      declval扔出窗外;当您的类型表达式依赖于函数参数、类成员和/或this 时,几乎可以肯定的是,将它放在尾随返回类型中会更容易、更清晰,您可以在其中通过名称引用它们:

      struct Derived
      : public Base
      {
          Derived() {}
          auto g() const -> decltype(f());
      };
      

      我向Derived 添加了一个用户提供的默认构造函数,以便const Derived x; 符合§8.5/6 的格式。

      【讨论】:

      • 在这个特定示例的上下文中,是的,它有效,但问题更“笼统”。
      • 问题是“我如何获得 X 的 declval”,而您的回答是“不要使用 declval”。已经证明可以实现 OP 所寻求的。我不能对此表示赞同。
      • @DanielFrey C++11 8.5/6 “如果程序要求对 const 限定类型 T 的对象进行默认初始化,则 T 应是具有用户提供的默认构造函数的类类型。”
      • @JohnDibling 问题是“如何修改 decltype(std::declval().f()) 使其返回 int 而不是 double ?”我通过消除“std::declval()”对其进行了修改。并将其从模板参数移动到尾随返回类型。这可能不是 OP期望 的答案,但它确实展示了如何以更少的代码达到预期的目的。
      • @DanielFrey CWG issue 253 存在。 GCC seems to have implemented the currently discussed resolution 尽管问题仍然存在?或者它可能在 2011 年重新开放。更正:问题不是“开放”,而是“起草”。
      猜你喜欢
      • 2022-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-28
      • 2016-06-02
      相关资源
      最近更新 更多