【问题标题】:C++0x decltype fails to deduce member variable constnessC++0x decltype 无法推导出成员变量 constness
【发布时间】:2011-02-08 21:05:33
【问题描述】:

考虑以下代码:

template <typename T>
class B
{
};

template <typename T>
B<T> f(T& t)
{
    return B<T>();
}

class A
{
    class C {};
    C c;
public:
    A() {}

    decltype(f(c)) get_c() const { return f(c); }
};

int main()
{
    A a;
    a.get_c();
}

当我尝试编译它时,我得到了错误:

test.cpp: In member function 'B<A::C> A::get_c() const':
test.cpp:31:46: error: conversion from 'B<const A::C>' to non-scalar type 'B<A::C>' requested

似乎在decltype中,编译器不知道这是一个const成员函数,因此c的类型为const C,结果错误地将f(c)的类型推断为@ 987654326@ 而不是 B&lt;const C&gt; 这才是真正的。

我做错了什么,或者这是一个编译器错误?我使用 gcc 4.6,但 4.4 和 4.5 表现出相同的行为。

【问题讨论】:

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


    【解决方案1】:

    编译器根据当前的 C++0x WP 正确运行。请参阅this issue report,目前正在开发中。

    可能最终的 C++0x 标准不会改变您的 decltype 应用程序在函数名称之前的返回类型中的含义。您需要使用-&gt; decltype(f(c)) 将其移动到参数列表之后,这有望在最终的 C++0x 中做正确的事情。

    【讨论】:

    • 请注意,C++11 确实包含了修复,因此您可以使用尾随语法来获得正确的 const 正确性。
    【解决方案2】:

    不,decltype 不应该考虑函数是否为 const,因为它不能。同样的写法也可以不同:

    typedef decltype(f(c)) return_type;
    
    return_type get_c() const { return f(c); }
    

    更正:decltype(f(c)) 甚至不应该编译,因为c 不是静态的。

    【讨论】:

    • 是的,它应该编译。在未评估的上下文中,您可以访问非静态数据成员。
    • @Johannes,我可能是错的,但据我记得只允许在函数体内访问非静态成员。如果上面的函数被修改为使用尾随返回类型,那么您可以访问非静态成员。
    • 是的,我认为你错了。在此处查看我对相关问题的回答:stackoverflow.com/questions/4849556/…
    • @TonyK,它在 g++ 4.4 下编译的事实并不是标准一致性的证明。该标准在 9.3.1/3 中规定,仅允许从函数体内部访问非静态成员,因此在这种情况下需要尾随返回类型。
    • N3225 没有这么说。仔细阅读它,然后你会发现它没有。另请参阅 5.1.1/10。
    【解决方案3】:

    f 需要采用右值引用,而不是左值引用。

    【讨论】:

      【解决方案4】:

      我不认为你可以在你通常不能调用的任何东西上使用 decltype。我无法在标准中找到任何允许您访问 c 的内容,即使在 decltype 表达式中,在您可以使用 c 的任何地方之外。由于您在尝试做您的事情时没有this 指针,所以我认为您无法做您想做的事情。这样做至少在 MSVC 2010 中不起作用,并且与 const 无关。

      我考虑过使用 declval 来获得一个,但您无法访问 A&&.c,因为此时 A 是不完整的类型。除了这样的事情之外,我无论如何都看不到你想做的事情:

      decltype(f(declval<C const>())) get_c() const { ... }
      

      【讨论】:

      • 相应的文本在 5.1.1/10 的最后一个项目符号处。
      • MSVC 没有此功能,因为它适用于较早的标准草案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-01
      • 1970-01-01
      • 2015-09-04
      • 1970-01-01
      • 2015-07-06
      相关资源
      最近更新 更多