Я хочу передать не-захватывающий лямбда, который возвращает std::unique_ptr<Derived>
, в качестве функции указателя типа std::unique_ptr<Base>(*)()
.Передача лямбда, которая возвращает polyorphic unique_ptr, в качестве указателя функции
Однако это работает только в том случае, если я явно указываю тип возврата лямбда как std::unique_ptr<Base>
.
- Почему я явно указываю тип возврата?
- Почему это работает для
std::function
без дополнительного типа возврата?
#include <functional>
#include <memory>
struct Base{virtual ~Base()=default;};
struct Derived : Base{};
struct FailsForF2
{
using Function = std::add_pointer_t<std::unique_ptr<Base>()>;
FailsForF2(Function f) {}
};
struct Works
{
using Function = std::function<std::unique_ptr<Base>()>;
Works(Function f) {}
};
std::unique_ptr<Derived> fun() {return std::make_unique<Derived>();}
int main()
{
auto f1 = [](){return std::make_unique<Base>();};
auto f2 = [](){return std::make_unique<Derived>();};
auto f3 = []()->std::unique_ptr<Base>{return std::make_unique<Derived>();};
Works x1(f1);
Works x2(f2);
Works x3(f3);
FailsForF2 x4(f1);
FailsForF2 x5(f2);
FailsForF2 x6(f3);
}
GCC ошибка:
main.cpp: In function 'int main()':
main.cpp:34:20: error: invalid user-defined conversion from 'main()::<lambda()>' to 'FailsForF2::Function {aka std::unique_ptr<Base> (*)()}' [-fpermissive]
FailsForF2 x5(f2);
^
main.cpp:26:17: note: candidate is: main()::<lambda()>::operator std::_MakeUniq<Derived>::__single_object (*)()() const <near match>
auto f2 = [](){return std::make_unique<Derived>();};
^
main.cpp:26:17: note: no known conversion from 'std::_MakeUniq<Derived>::__single_object (*)() {aka std::unique_ptr<Derived> (*)()}' to 'FailsForF2::Function {aka std::unique_ptr<Base> (*)()}'
main.cpp:10:4: note: initializing argument 1 of 'FailsForF2::FailsForF2(FailsForF2::Function)'
FailsForF2(Function f) {}
не будет 'std :: add_pointer_t>;' быть указателем на 'unique_ptr '? См. Http://coliru.stacked-crooked.com/a/5a1c461bfb6199a8 Возможно, я не эксперт, но могу угадать, что у компилятора есть проблема с преобразованием 'unique_ptr ' в указатель на 'unique_ptr ' при конвертировании a 'unique_ptr ' указателю на 'unique_ptr ' он может как-то делать неявно –
Hayt
@Hayt Я использую 'std :: add_pointer_t()>;' обратите внимание на '()' в конце –
Да, да. Никогда не думай об этом.Возможно, что-то нужно сделать с другим поведением функции ptr (которое является первым) и объектом функции с некоторым преобразованием, но я не мог найти никаких ссылок на это прямо сейчас (в комбинациях с lambdas. Возможно, что-то с конверсией от lambda до c-функции ptr). – Hayt