Как ссылаться на собственный тип в аргументах шаблона по умолчанию?
У нас есть reference_counted
шаблон и дефолт default_deallocator
Класс следующим образом:
template <class T>
class default_deallocator {
void operator()(T* obj) {
delete obj;
}
};
template <class T>
class reference_counted: T
{
public:
void retain() {ref_count++;}
void release() {
ref_count --;
if (ref_count == 0) {
delete this;
}
}
}
Мы хотим добавить Deloclocator для reference_counted
учебный класс. Но мы не знаем, как написать аргумент шаблона по умолчанию, потому что компилятор будет жаловаться на рекурсивную ссылку на тип.
//VS2015 says: fatal error C1202: recursive type or function dependency context too complex
template <class T, class D = default_deallocator<reference_counted<T>>> <---
class reference_counted: T
{
public:
void retain() {ref_count++;}
void release() {
ref_count --;
if (ref_count == 0) {
D deallocator;
deallocator.operator()(this);
}
}
}
Я понимаю эту ошибку. Итак, вопрос в том, как ссылаться на текущий тип класса в аргументе шаблона по умолчанию или как реализовать этот шаблон проектирования?
2 ответа
Решение
Вы можете использовать тип с более высоким родом ("параметр шаблона шаблона"):
template <class T, template <typename...> class D = default_deallocator>
class reference_counted: T
{
public:
void retain() {}
void release() {
D<reference_counted<T, D>> deallocator;
deallocator(this);
}
};
template <class T, class D_in = void>
class reference_counted: T
{
public:
using D = std::conditional_t<
std::is_same<D_in, void>,
default_deallocator<reference_counted>,
D_in
>;
void retain() {ref_count++;}
void release() {
ref_count --;
if (ref_count == 0) {
D deallocator;
deallocator.operator()(this);
}
}
};