2016-06-14 1 views
3

мне любопытно, почему следующий шаблон вычет не работает (VS2015):Шаблон функции члена вывод аргумента

template<typename T> 
class Foo 
{ 
public: 
    template<typename U> 
    U get(U u) { return u; } 

    // Default constructed U and T for example only. 
    template<typename U> 
    U get(std::function<U(U, T)> f) { return f(U(), T()); } 

    template<typename U> 
    U get(U u, std::function<U(U,T)> f) { return u; } 

}; 

В приведенном выше примере, следующий успешна:

Foo<int> f; 
auto f_asInt = f.get(5);  // f_asInt is of type int 
auto f_asFloat = f.get(5.0f); // f_asFloat is of type float. 

auto ff_asInt = f.get([](int, int) { return 5; }); 
auto ff_asFloat = f.get([](float, int) { return 5.0f; }); 

следующая однако не удается скомпилировать

Foo<int> f; 
auto f_asInt = f.get(5, [](int, int) { return 5; }); 
auto f_asFloat = f.get(5.0f, [](float, int) { return 5.0f; }); 

Я получаю следующее сообщение об ошибке:

error C2784: 'U Foo<int>::get(U,std::function<U(U,T)>)': could not deduce template argument for 'std::function<U(U,T)>' from 'main::<lambda_c4fa8cb1e6fa86997f25b7dabd5d415f>' 

Если я изложу весь шаблон, он работает должным образом.

Foo<int> f; 
auto f_asInt = f.get<int>(5, [](int, int) { return 5; }); 
auto f_asFloat = f.get<float>(5.0f, [](float, int) { return 5.0f; }); 

Я бы хотел, чтобы аргументы шаблона были выведены в этом случае, возможно ли это?

+0

Я должен был отметить, VS2015. – lcs

+2

@SergeyA Какая часть «компилируется в порядке»? Это не должно компилироваться по обычной причине. –

+0

@SergeyA: Сбой с clang и gcc [Demo] (http://coliru.stacked-crooked.com/a/8985d5f62d8f258e). – Jarod42

ответ

4

Это не работает, потому что тип std::function не может быть выведен из лямбда. Компилятор не знает, для чего F a std::function<F> может быть построен из данной лямбда. Последние два примера в первом блоке работают только потому, что используется перегрузка get(U u), а не одна с аргументом std::function.

Если вы хотите, чтобы иметь возможность принимать lambdas, вам необходимо иметь перегрузку, которая принимает общий тип вызываемого типа, а не std::function. Трудно дать более конкретное направление, если вы не объясните, что вы пытаетесь сделать.

 Смежные вопросы

  • Нет связанных вопросов^_^