12

C++0xラムダについて質問があります。私のコードでは、特定の型がC++0xラムダ式の型であるかどうかを知ることが有益です。例を挙げると:

struct foobar
{
  void operator()()
  {
  }
};

auto lambda = []{};
typedef is_lambda < decltype(lambda) > ::type T; // T would be a true_type
typedef is_lambda < foobar > ::type T; // T would be a false_type

ラムダ式を関数およびメンバー関数タイプと区別するのはかなり簡単です。ファンクターは別の問題です。

ここで私が目にする問題は、次のC++0x標準に従ったラムダ式の定義です。定義する必要があるのは、パブリックコール演算子だけです。ただし、これはファンクターにも当てはまります。呼び出し演算子の存在をテストするだけでは、ラムダ式とファンクターを区別するのに十分ではありません。さらに、ファンクターのオペレーターが存在しない場合、SFINAEが適用されないため、コンパイラー・エラーが発生します。これはいつ起こりますか?ファンクターの呼び出し演算子はテンプレート化できます。したがって、そのようなコード:

typedef decltype(&T::operator()) call_type;

テンプレート化されていない呼び出し演算子を使用してラムダ式とファンクターの両方で機能し、テンプレート化された呼び出し演算子のコンパイラエラーを生成します。

is_lambda < >トレイトは、組み込みのコンパイラ機能を使用してのみ作成できると思います。この特性を実装する方法がわかりますか?

4

4 に答える 4

8

ラムダを評価するとクロージャオブジェクトが作成されるため、オブジェクトが関数に渡されるかコピーされるとすぐに違いはありません。そして、率直に言って、オブジェクトがラムダから来たかどうかを知る必要がある問題を想像することはできません。

編集。標準には、5.1.2/2にも注記があります。

注:クロージャオブジェクトは関数オブジェクト(20.8)のように動作します。—エンドノート

于 2011-01-11T19:55:08.493 に答える
6

ラムダは実際には意味的に新しいものではなく、コンパイラによって生成されたファンクタであるため、通常のファンクタと同じように見えます。

于 2011-01-11T19:54:05.553 に答える
2

式がラムダ式であるかどうかを判断するマクロコードを定義することは可能です(ただし、式がラムダであるかどうかはわかりません)。

#include <type_traits>

template<typename T, typename U>
struct SameType {
    static_assert(!std::is_same<T, U>::value, "Must use Lambda");
    static T pass(T t) { return t; }
};

template <typename T, typename U>
T NotLambda(T t, U u) { return SameType<T, U>::pass(t); }

#define ASSERT_LAMBDA(x) NotLambda(x,x)

/////////////////////////////////////

int fn() { return 0; }

int main() {
    auto l = []{ return 0; };
    return ASSERT_LAMBDA(fn)() +             // << fails
           ASSERT_LAMBDA(l)() +              // << fails
           ASSERT_LAMBDA([]{ return 0; })(); // << passes
}

これは、各ラムダ式が異なるタイプ(ラムダに固有のプロパティだと思います)を持つことを指定するセクション5.1.2.3に依存します。

于 2014-03-28T22:31:11.013 に答える
1

興味のある人がいれば、ヘッダーのみのコンパイラ固有(msvc> = 19.20?、gcc> = 7.3、clang> = 6.0)is_lambdaタイプの特性をc++17で作成しました。

https://github.com/schaumb/is_lambda-cpp-type-trait

これは、質問のように使用できます。

struct foobar
{
  void operator()()
  {
  }
};

auto lambda = []{};
typedef bxlx::is_lambda < decltype(lambda) > T; // T is true_type
typedef bxlx::is_lambda < foobar > U; // U is false_type

使用例は他にもあります。


于 2020-01-14T15:08:49.543 に答える