Я пытаюсь создать библиотеку журналирования, в которой пользователь мог бы выбрать запись в выходной файл или в файл, или в оба. Я хочу создать один класс, который обрабатывает запись (а позже и другие вещи, связанные с потоком).
Очевидной реализацией было бы использование оператора if для всех функций, но я хотел оптимизировать это, используя специализацию шаблонов . Я создал класс под названием DoubleStreamWriter
:
template <typename _FST, typename _OST>
class DoubleStreamWriter {
public:
DoubleStreamWriter(_FST fst, _OST ost) {
fst_ = fst;
ost_ = ost;
}
template <typename WT>
void Write(WT obj) {
(*fst_) << obj;
(*ost_) << obj;
}
void Flush() {
fst_->flush();
ost_->flush();
}
private:
_FST fst_;
_OST ost_;
};
template <>
class DoubleStreamWriter <std::nullptr_t, std::ostream*> {
public:
DoubleStreamWriter(std::nullptr_t fst, std::ostream* ost) {
(void)fst;
ost_ = ost;
}
template <typename WT>
void Write(WT obj) {
(*ost_) << obj;
}
void Flush() {
ost_->flush();
}
private:
std::ostream* ost_;
};
template <>
class DoubleStreamWriter <std::ofstream*, std::nullptr_t> {
public:
DoubleStreamWriter(std::ofstream* fst, std::nullptr_t ost) {
(void)ost;
fst_ = fst;
}
template <typename WT>
void Write(WT obj) {
(*fst_) << obj;
}
void Flush() {
fst_->flush();
}
private:
static std::ofstream* fst_;
};
template <>
class DoubleStreamWriter <std::nullptr_t, std::nullptr_t> {
public:
DoubleStreamWriter(std::nullptr_t fst, std::nullptr_t ost) {
(void)fst;
(void)ost;
std::cout << ">>> cannot log anything with those settings" << std::endl;
}
template <typename WT>
void Write(WT obj) {
(void)obj;
}
void Flush() {
}
};
Класс регистратора - это синглтон, который имеет частный указатель (dwriter_
) этого типа. Однако я, очевидно, не могу изменить тип шаблонов во время инициализации, например, не могу преобразовать DoubleStreamWriter<ofstream*, ostream*>
в DoubleStreamWriter <std::nullptr_t, ostream*>
. Я попытался «исправить» это, используя вместо этого void*
, но это просто отложило проблему до времени выполнения и было очень некрасиво.
Моя ошибка заключалась в том, что я думал, что decltype(stream_ptr)
возвращает std::nullptr_t
if stream_ptr
установлено nullptr
.
Как лучше всего это сделать? в качестве альтернативы, есть ли способ получить тот же тип, что и decltype(nullptr)
, при вызове decltype
для указателя, установленного на nullptr
?