4

コンパイラが最も明白なオーバーロードを選択できないのはなぜですか。

#include <iostream>
#include <functional>

static void foo(const std::function<void(bool)>& f) {
    std::cerr << "using bool overload" << std::endl;
    f(true);
}

static void foo(const std::function<void(int)>& f) {
    std::cerr << "using int overload" << std::endl;
    f(1);
}

int main() {
    foo([](const bool value) {
        std::cout << std::boolalpha << value << std::endl;
    });
    foo([](const int value) {
        std::cout << value << std::endl;
    });
    return 0;
}

出力は次のようになります。

using bool overload
true
using int overload
1

ただし、コンパイラは正しいオーバーロードを推測できません。

gcc-4.8:

main.cpp: In function 'int main()':
main.cpp:17:6: error: call of overloaded 'foo(main()::__lambda0)' is ambiguous
     });
      ^
main.cpp:17:6: note: candidates are:
main.cpp:4:13: note: void foo(const std::function<void(bool)>&)
 static void foo(const std::function<void(bool)>& f) {
             ^
main.cpp:9:13: note: void foo(const std::function<void(int)>&)
 static void foo(const std::function<void(int)>& f) {
             ^

clang-3.4:

main.cpp:15:5: error: call to 'foo' is ambiguous
    foo([](const bool value) {
    ^~~
main.cpp:4:13: note: candidate function
static void foo(const std::function<void(bool)>& f) {
            ^
main.cpp:9:13: note: candidate function
static void foo(const std::function<void(int)>& f) {
            ^

これは、std::functionコンストラクターがパラメーターを自動的に消費して変換するためですか?

4

2 に答える 2

0

ラムダはファンキーな構文を持っているかもしれませんが、それでもファンクタです。つまり、それらは を定義しますunique_type::operator()(Args...)。これは、ラムダのキャプチャにも当てはまります。キャプチャされた値は、ラムダ オブジェクトのメンバーです。

したがって、次のコードはラムダ オブジェクトを分解します。

template<typename T, typename R, typename A>
void bar(T const& t, R (T::*pmf)(A));

template<typename LAMBDA>
void foo(LAMBDA const& l)
{
  bar(l, &LAMBDA::operator());
}

明らかに、例の 2 つのラムダを区別する必要がある場合は、barテンプレート化されていない 2 つの関数に置き換えることができます。OTOH、任意の数の引数でラムダをサポートする必要がある場合は、bar.

于 2013-11-13T13:22:35.503 に答える