使用专用析构函数绕过模板错误
Bypass a template error with a private destructor
在编译时,我遇到了以下问题,如何进行编译,因为从概念上讲,这是正确的,欢迎任何重构建议。
我得到了一个编译错误,因为"搜索"析构函数是私有的,但我不会在搜索指针上使用delete,因为我在初始化基类时提供了一个自定义Deleter。我知道编译器不知道如何绕过它。
错误描述:错误C2248:无法访问类"Search"中声明的私有成员编译器已在此处生成"搜索::~Search">
class Search
{
public:
static Search* New(/* */); // using a pool of already allocated objects to avoid expensive allocations
static void Delete(Search*);
private:
Search(/* */) {/* */}
~Search() {/* */}
};
template<class T>
class MyList
{
public:
typedef (*CustomDeleter) (T* pElement);
MyList(CustomDeleter lpfnDeleter = NULL) {};
void Empty()
{
for (/**/)
{
if (m_pList[m_nListLastUsed])
{
if (m_lpfnCustomDeleter == NULL)
delete m_pList[m_nListLastUsed]; // COMPILE ERROR HERE BECAUSE Search destructor is private BUT I won't use that instruction since
// I provided a custom Deletern I know that the compiler doesn't know that, how to bypass it
else
m_lpfnCustomDeleter(m_pList[m_nListLastUsed]);
}
}
}
private:
T** m_pList;
CustomDeleter m_lpfnCustomDeleter; // Pointer to a custom deleter
};
class Query : public MyList<Search>
{
public:
Query() : MyList<Search>(&Search::Delete) // I set a custom deleter since Search hides its destructor : is this the right way ?
{}
~Query()
{
/****/
Empty(); // PROBLEM HERE
/***/
}
};
确保'm_lpfnCustomDeleter'从不为NULL或更好的nullptr。如果用户没有提供任何自定义删除程序,则可以通过回退到默认的"删除程序"来确保这一点。
我想要下面这样的。
#include <iostream>
template <typename PointerType>
struct DefaultDeleter {
void operator()(PointerType* ptr) {
std::cout << "Deleten";
}
};
struct CustomDeleter {
void operator()(int* ptr) {
std::cout << "Custom int deleter" << std::endl;
}
};
template <typename T, typename Deleter = DefaultDeleter<T>>
class Whatever
{
public:
Whatever() {
std::cout << "Consn";
}
void deinit() {
Deleter d;
auto v = new T;
d(v); // Just for the sake of example
}
};
int main() {
Whatever<char> w;
w.deinit();
Whatever<int, CustomDeleter> w2;
w2.deinit();
return 0;
}
更新::不进行代码重构假设不进行c++11
把这个小的元程序添加到你的代码库中。
命名空间my{
template <typename T, typename U> struct is_same { static const bool value = false; }; template <typename T> struct is_same<T, T> { static const bool value = true; }; template <bool v, typename T = void> struct enable_if; template <typename T = void> struct<true, T> { typedef T type; }; }
将清空功能更改为:
void Empty(){for(/****/){do_delete();}}
template<typename=typename my::enable_if<my::is_same<T、 搜索>::value>::type>void do_delete(){assert(m_lpfnCustomDeleter!=NULL);m_lpfnCustomDeleter(m_pList[m_nListLastUsed]);}无效do_delete(){删除m_pList[m_nListLastUsed];}
如果您使用的是c++11,则不必在命名空间"my"下编写元程序。只需将"my::is_same"answers"my::enable_if"替换为"std::is_ame"answers"std::enable_idf"。
注意:,尚未编译和测试上述代码。
将执行删除的代码与其他代码分开:
if (m_pList[m_nListLastUsed])
{
if (m_lpfnCustomDeleter == NULL)
delete m_pList[m_nListLastUsed]; // COMPILE ERROR HERE BECAUSE Search destructor is private BUT I won't use that instruction since
// I provided a custom Deletern I know that the compiler doesn't know that, how to bypass it
else
m_lpfnCustomDeleter(m_pList[m_nListLastUsed]);
}
将上面的代码替换为调用:
custom_delete(m_pList[m_nListLastUsed]);
然后将其添加为列表类的方法,不要忘记还包括<type_traits>
:
std::enabled_if<std::is_destructible<T>::value, void>::type custom_delete(T* ptr) {
/* Note: this isn't pre-2000 anymore, 'lpfn' as a prefix is horrible,
don't use prefixes! */
if (m_lpfnCustomDeleter) {
m_lpfnCustomDeleter(ptr);
} else {
delete ptr;
}
}
std::enabled_if<!std::is_destructible<T>::value, void>::type custom_delete(T* ptr) {
if (!m_lpfnCustomDeleter) {
throw "No custom deleter for a non destructible type!";
}
m_lpfnCustomDeleter(ptr);
}
如果对象具有私有析构函数,则enabled_if
将使它可以直接delete
对象的函数不存在于您的列表中。
或者,您可以传递一个充当自定义deleter的结构(或函数)作为列表的第二个模板参数,并将默认值作为调用delete运算符的参数,然后直接在指针上调用此结构,如Arunmu的anser中所示。
- C++类错误中的模板专用化
- 模板专用化会导致未定义的引用错误
- flat_hash_map.h:错误 C3203:"templated_iterator":非专用类模板
- C++ 将派生类的成员函数指针作为参数传递时选择了错误的模板专用化
- cpp 模板专用化,错误说参数 1 的类型为 T,这取决于参数 T
- 类模板部分专用化:编译器错误
- 为什么在源文件中专用模板不会导致错误?
- 函数模板(它是类模板的成员)的显式专用化会产生"partial specialization is not allowed"错误,为什么?
- C++模板 - 使用"std::is_same_v"而不是专用并避免编译错误?
- VS2017模板专用化错误无法从'Class *(__cdecl *)(Args...)'转换为'Class *(__cdecl *)(Args...)'
- 函数模板专用化生成链接错误
- 错误 C2908:显式专用化; 已被实例化
- 部分模板专用化错误
- 模板函数专用化的内部编译器错误
- 类模板方法的专用化,类型名称是类模板 - 错误:参数处的类型/值不匹配
- 错误 C2893:无法使用 CTPL 专用化函数模板
- gcc中变量模板的错误显式模板专用化
- Qt nmake:错误 C3203:"map":非专用类模板不能用作模板参数"base"的模板参数,预期为真实类型
- 声明无法解决"实例化后的显式专用化"错误
- 需要"override"案例时重叠模板部分专用化:如何避免错误?