Я создаю объектный файл для моей более крупной программы. В этой программе я использую тип unique_ptr
с определенным настраиваемым средством удаления.
Итак, я компилирую свой файл так:
g++ -std=c++20 tmp.cpp -c -Wall
Код выглядит следующим образом:
#include <memory>
using specialptr = std::unique_ptr<int, decltype([](int *f) {
delete f;
})>;
specialptr fun(){
return specialptr{new int};
}
Это генерирует это предупреждение:
tmp.cpp:12:12: warning: ‘specialptr fun()’ defined but not used [-Wunused-function]
12 | specialptr fun(){ return specialptr{new int};}
|
Когда я связываю этот объектный файл с main.cpp
, который вызывает функцию, я получаю следующую ошибку:
In file included from main.cpp:1:
tmp.h:19:12: warning: ‘specialptr fun()’ used but never defined
19 | specialptr fun();
| ^~~
/usr/bin/ld: /tmp/ccnuTTGC.o: in function `main':
main.cpp:(.text+0x4c): undefined reference to `fun()'
collect2: error: ld returned 1 exit status
Что здесь происходит? Мой код работает, когда я меняю возвращаемое значение с unique_ptr
на обычный указатель. Но интуитивно я определил тип и функцию и сделал объявление в заголовочном файле.
g++ — это версия: g++ (Ubuntu 11.3.0-1ubuntu1~22.04) 11.3.0
decltype
лямбды отличается для каждой единицы перевода.
Вместо этого вы можете сделать что-то вроде:
struct specialptr_deleter {
void operator()(int *f) const {
delete f;
}
};
using specialptr = std::unique_ptr<int, specialptr_deleter>;
specialptr fun(){
return specialptr{new int};
}
@TarickWelling На самом деле вы не можете забыть указать удаление с таким типом. В этом случае компилятор его не скомпилирует. Но вы можете случайно или специально создать указатели с разными реализациями удаления.
В этом случае вы можете использовать структуру. Смотрите мой обновленный ответ
Вы можете использовать тип объекта в качестве удаления. В этом случае вам не нужно устанавливать его каждый раз, когда вы создаете std::unique_ptr
.
#include <memory>
#include <iostream>
struct MyDeleter {
void operator()(int *f) {
std::cout << "Deleter called";
delete f;
}
};
using specialptr = std::unique_ptr<int, MyDeleter>;
specialptr fun(){
return specialptr{new int};
}
int main()
{
auto x = fun();
}
Ах да ладно. Но это означало бы ставить
Deleter
каждый раз, когда я используюspecialptr
, верно? Это оставляет открытой возможность того, что я забуду дать ему правильное удаление. ммч