7

(ここでの根本的な問題は、ラムダを含む複雑な式でdecltype、またはおそらく に基づく他の型推論を使用しようとしてautoいるということです。何らかの回避策を見つけようとしています。http: //pfultz2.github.com/Pythy/ポリモーフィック ラムダについて。

decltype([](int){return 3.5L};ラムダの型、または少なくとも戻り値の型を取得できるようにしたいと考えています。はい、ラムダには一意の型が与えられることを知っていますdecltype([](int){return 3.5L};。2 つの異なる行で使用すると、2 つの異なる型が与えられることを思い出す必要はありません。

ラムダで使用するdecltypeと、エラー メッセージが表示されます (「未評価のコンテキストで使用されるラムダ」)。これは合理的なエラー メッセージのように思えますが、C++ がそのように手を握っているのには驚きました。特にラムダの戻り値の型にアクセスするために、これを行うことができると便利です。このエラーは単にエラー メッセージが多すぎるために発生したものですか?それとも、それを実行できない正当な理由があるのでしょうか?

このような式は、メンバー関数内で機能します。

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>’

これは、ラムダで型推論を行うために、関数で静的変数を使用しようとする私のアイデアに影響を与えました。

X がテンプレートでない場合、これは少しうまくいくようです。しかし、X をテンプレートにする必要があります。特に、ラムダへの引数はテンプレート パラメーターの型を取ります。

ラムダの型だけが必要であり、戻り値の型だけで満足することを覚えておいてください。どちらの場合も、コンパイラが型推論と静的初期化を喜んで実行できるのはイライラしますが、私のやり方には恣意的な障害があるようです。

関数の外から変数のにアクセスできますか?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
};

にラムダがあるa_complicated_expression...場合、 の初期化子に問題があることがよくありますmemberSが実際に構造体テンプレートの場合、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) でのラムダの使用について不平を言うので、私はできません。

を使用してg++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3います。g++ 固有の拡張機能を使用する必要があるかどうかは気にしません。

4

2 に答える 2

1

非キャプチャ ラムダは関数ポインターに変換でき、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;});vartype を持つことになりますdouble (*)(int)

staticただし、ラムダをクラススコープの初期化子として使用することはできません。lambda を static member として参照してください。

于 2012-09-04T11:42:24.177 に答える
0

ラムダ関数は、そのスコープのコンテキストでのみ定義されます。これは、静的メンバー関数内のラムダ関数が、他の場所で定義されているものとは異なる型であることを意味します。スコープ外でラムダ関数の戻り値の型を取得することは賢明ではなく、可能であってはならないと私には思えます。

潜在的なラムダ関数の範囲外でそのような型を定義することは明らかに理にかなっているからです。

于 2012-09-04T11:32:47.550 に答える