#c #g #c 17 #clang
Вопрос:
Это какая-то заводская лямбда. Класс, экземпляр которого должен быть создан лямбда, получает ссылку на другой класс в своем конструкторе. Если последний объявляет член unique_ptr, возникает действительно длинная ошибка:
#include <memory>
#include <string>
struct A
{
std::unique_ptr<int> foo;
};
struct B
{
B(const std::string amp; str, Aamp;a) {}
};
template<typename T, typename ... Args>
auto registerType(const std::string amp; type, Argsamp;amp; ... args)
{
return [args = std::make_tuple(std::forward<Args>(args) ...)]() mutable -> auto
{
return std::apply([](autoamp;amp; ... args){
return std::make_unique<T>(args ...);
}, std::move(args));
};
}
int main()
{
A a;
registerType<B>("lala", "p1", a)();
}
Удаление элемента unique_ptr работает нормально.
Передача указателя на «a» вместо ссылки также работает нормально.
Вывод ошибок длинный, лучше увидеть его в действии:
https://godbolt.org/z/n896qMz59
Это происходит, по крайней мере, с:
- g 9.2.0 и магистраль
- лязг ствол
Есть какие-нибудь идеи?
Спасибо
Комментарии:
1. Ошибка в том, что:
no matching function for call to 'std::tuple<const char*, A>::tuple(const char [3], Aamp;)
2.
registerType<B>("lala", "p1", std::move(a))();
godbolt.org/z/W88hTrT48
Ответ №1:
Вы не можете скопировать unique_ptr
А.
Но ты можешь передвинуть его:
#include <utility>
// ...
registerType<B>("lala", "p1", std::move(a))();
или предотвратите std::decay
, чтобы при использовании make_tuple
не произошло:
return [args = std::tuple<Args...>(std::forward<Args>(args) ...)]() mutable -> auto
Комментарии:
1. Однако вы все равно можете передать его в качестве ссылки, если сделаете
std::ref(a)
это, но это, несомненно, вызовет другие проблемы2. Ах… так просто… Хорошо, я знаю, что не могу не скопировать unique_ptr, но не могли бы вы, пожалуйста, сказать мне, где в выводе ошибок, полном ошибок кортежа, есть хотя бы намек на это? И почему его копируют?
3. @osovan
std::make_tuple
уничтожает свои аргументы, удаляя ссылки и, следовательно, делая копиюstruct A
того, что изначально было передано какa
. видишь en.cppreference.com/w/cpp/utility/tuple/make_tuple4. @osovan Вывод ошибок отличается для разных компиляторов — ни один из них не поддается легкому анализу. 🙂 Да, это распад внутри
make_tuple
. Я добавил опцию, чтобы предотвратить это.5. @TedLyngmo Спасибо за добавление опции.