如何使用类自身方法的返回类型定义类的内部别名?

问题描述 投票:0回答:1

考虑下面的代码:

struct LambdaWrapper {
    auto getLambda() {
        return []() {
            std::cout << "Lambda is called" << std::endl;
        };
    }
};

void useLambda(auto &&lambda) {
    lambda();
}

int main() {
    LambdaWrapper w;
    useLambda(w.getLambda());
    return 0;
}

我将

auto
用于
LambdaWrapper::getLambda()
返回类型和
useLambda()
函数的参数。但实际上在这段代码中使用了唯一的类型,这就是
LambdaWrapper::getLambda()
返回的内容,所以我可以为该类型定义一个别名:

struct LambdaWrapper {
    auto getLambda() { ... }
    static LambdaWrapper* get();
};

using LambdaType = decltype(LambdaWrapper::get()->getLambda());
void useLambda(const LambdaType &lambda);

现在我希望使这个别名成为

LambdaWrapper
类的一部分:

struct LambdaWrapper {
    auto getLambda() { ... }
    static LambdaWrapper* get();
    using LambdaType = decltype(LambdaWrapper::get()->getLambda());
};

void useLambda(const LambdaWrapper::LambdaType &lambda);

但现在我明白了

错误:在扣除“auto”之前使用“auto LambdaWrapper::getLambda()”

我如何在类中定义这个别名?

c++ alias using decltype
1个回答
0
投票

问题在于类是分两遍解析的。在第一遍中,编译器会看到声明

auto getLambda()
(不是定义)和
using LambdaType = decltype(LambdaWrapper::get()->getLambda());
,但是,由于尚无
getLamba
的定义可用,因此解析失败。这就是为什么编译器在推断返回类型之前告诉您正在使用
getLambda()

如果您使用 C++20,解决方案很简单。您可以将 lambda 的定义移至

decltype
,假设它没有捕获:

struct LambdaWrapper {
    using LambdaType = decltype( []() {
            std::cout << "Lambda is called" << std::endl;
    });
    LambdaType getLambda() {
        return {};
    }
};

请参阅编译器资源管理器中的实时示例

适用于旧标准的更通用解决方案是将 lambda 表达式移至单独的作用域,例如基类:

// note: You can also put getLambda() into a namespace, not into a class.
//       I suspect your example is overly minimal and you can't actually do that.
struct LambdaProvider {
    auto getLambda() {
        return []() {
            std::cout << "Lambda is called" << std::endl;
        };
    }
};

struct LambdaWrapper : LambdaProvider {
    using LambdaType = decltype(std::declval<LambdaProvider>().getLambda());
    LambdaType getLambda() {
        return {};
    }
};

请参阅编译器资源管理器中的实时示例

您甚至可以将

LambdaProvider
转换为 CRTP(奇怪的重复模板模式),以便您可以访问其中的
LambdaWrapper
的成员函数。

© www.soinside.com 2019 - 2024. All rights reserved.