7

(这里的根本问题是我试图在涉及 lambdas 的复杂表达式上使用decltype,或基于 的其他类型推导auto。我试图找到某种解决方法。我一直在玩http: //pfultz2.github.com/Pythy/用于多态 lambda。如果不告诉大家一个长篇故事,我无法完全进入动机!)

我希望能够decltype([](int){return 3.5L};获取 lambda 的类型,或者至少是返回类型。是的,我知道 lambdas 被赋予了一个独特的类型,我不需要提醒decltype([](int){return 3.5L};如果在两条不同的行上使用它会给出两种不同的类型。

如果我decltype在 lambda 上使用,则会收到一条错误消息(“lambda used in unevaluate context”)。我知道这似乎是一个合理的错误信息,但我对 C++ 如此握着我的手感到惊讶!允许这样做会很有用,尤其是访问 lambda 的返回类型。这个错误仅仅是由于过分热心的错误信息造成的,还是真的有充分的理由不能做到这一点?

像这样的表达式在成员函数中起作用:

template<typename T>
struct X {
    void foo() {
        static auto l = [](int){return 3.5;};
    }
};

但我不允许这样做:

template<typename T>
struct X {
    static auto var = [](int){return 3.5;}; // will also fail if I use constexpr here
};

x.cpp:8:47: error: expression ‘#‘lambda_expr’ not supported by
    dump_expr#<expression error>’ is not a constant-expression
x.cpp:8:47: error: unable to deduce ‘const auto’ from ‘&lt;expression error>’

这激发了我尝试在函数中使用静态变量以对 lambda 进行类型推断的想法。

如果 X 不是模板,这似乎会更好一些。但我需要 X 是一个模板——特别是,lambda 的参数将采用模板参数的类型。

请记住,我只想要 lambda 的类型,并且只对返回类型感到满意。令人沮丧的是,编译器愿意并且能够在这两种情况下进行类型推断和静态初始化,但这似乎给我设置了一些任意障碍。

我可以从函数外部访问变量的类型吗?var_in_funcdummy_func

struct S {
    constexpr static auto member = a_complicated_expression...  // error
    void dummy_func() {
        static auto var_in_func = a_complicated_expression...    // OK
    }
    typedef dummy_func :: var_in_func the_type; // I'd like this to work
};

如果 中有 lambda a_complicated_expression...,则 的初始化程序通常会出现问题member。如果S实际上是一个结构模板,那么我会收到member没有初始化程序的错误消息。这就是为什么我试图找到其他方法来解决这个问题。

但是,static auto静态方法中的变量dummy_func可以正常工作。所以这让我想到它们应该是访问该静态变量类型的好方法?

我尝试了以下方法,但它不起作用,因为dummy_func它不是一种类型(足够公平):

typedef dummy_fun :: var_in_func the_type_of_the_static_variable_in_the_method;

我不能这样做decltype( a_complicated_expression... ),因为编译器抱怨在未评估的上下文(declspec)中使用 lambda。

我正在使用g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3. 我不介意我是否必须使用 g++ 特定的扩展。

4

2 回答 2

1

非捕获 lambda 可以转换为函数指针,并具有operator()该函数指针的签名:

template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...)) -> R(*)(Args...);
template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...) const) -> R(*)(Args...);
template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...) volatile) -> R(*)(Args...);
template<typename C, typename R, typename... Args>
auto remove_class(R (C::*)(Args...) const volatile) -> R(*)(Args...);

template<typename T>
auto to_f_ptr(T t) -> decltype(remove_class(&T::operator())) { return t; }

您现在可以编写auto var = to_f_ptr([](int){return 3.5;});并且var将拥有 type double (*)(int)

但是,您仍然不能将 lambda 用作类范围的static初始化程序;将lambda 视为静态成员

于 2012-09-04T11:42:24.177 回答
0

lambda 函数仅在其范围的上下文中定义。这意味着静态成员函数中的 lambda 函数与其他地方定义的类型不同。在我看来,在其范围之外获取 lambda 函数的返回类型是不明智的,也不应该是可能的。

必须有另一种方法(不涉及 lambda)来获得您需要的类型,因为在任何潜在 lambda 函数的范围之外定义这种类型显然是有意义的。

于 2012-09-04T11:32:47.550 回答