12

我在下面的代码编译时出错。

struct B{
    double operator()(){
        return 1.0;
    }
};

struct A {
    auto func() -> decltype(b())
    {
        return b();
    }

    B b;
};

但是,如果我重新组织A,它会编译。

gcc 4.8 表示未在此范围内声明“b”。

struct A {
    B b;
    auto func() -> decltype(b())
    {
        return b();
    }
};

那么,第一个有什么问题??

4

3 回答 3

11

它有效吗?

您的最后一个示例格式正确,而第一个示例格式不正确(因此 GCC 是正确的)。

关于不合格名称查找的第 3.4.1/7 段规定:

X 成员函数体、默认参数、非静态数据成员的大括号或等号初始化器或嵌套类定义之外的类定义中使用的名称应以下列方式之一声明

在其在类中使用之前X或成为 X (10.2) 的基类的成员之前,或

— [...]

以下是不适用于您的情况的其他条件。

于 2013-05-21T09:20:51.137 回答
9

的定义class经过两次处理:首先收集成员声明,​​包括函数签名,然后解析定义的主体。

因此,函数体可以访问所有成员声明,​​包括后续声明,但函数原型只能看到前面的声明。

于 2013-05-21T09:25:29.830 回答
1

你也可以让它像这样工作:

struct B
{
    double operator()()
    {
        return 1.0;
    }
};

// my implementation does not have std::declval
template < typename T > T&& declval();

struct A
{
    B b;
    auto func() -> decltype(declval<B>().operator()())
    {
        return b();
    }
};

编辑:或者因为 B 已经在范围内,所以不需要自动,-> decltype 和 declval

struct A
{
    B b;
    decltype(Q()()) func()
    {
        return b();
    }
};
于 2013-05-21T10:05:35.567 回答