C++ включить if (или обходной путь) для оператора-члена
template<typename T>
struct foo
{
T* p;
foo(T* x) : p(x) {}
~foo() { if(p) delete p; }
T& operator*() const { return *p; }
};
int main()
{
foo<int> i(new int);
foo<void> v(new int); // <= illegal use of type 'void'
}
Если T = void, то я не хочу реализовывать оператор*(). Как я могу этого достичь? Я не хочу специализировать класс, потому что в моем классе есть много других методов.
PS: Пожалуйста, обратите внимание, что это всего лишь пример, чтобы объяснить мою проблему.5 ответов:
Стандарт C++11 решил это для
std::unique_ptr
примерно так:typename std::add_lvalue_reference<T>::type operator*() const { return *p; }
Вы можете переместить все остальные методы (которые хорошо работают с
T==void
) в базовый класс и сделатьfoo
производными от него. Тогдаfoo
можно специализировать, чтобы не объявлятьoperator*
дляT==void
template <typename T> struct foobase { T* p; foobase(T* x) : p(x) {} ~foobase() { if(p) delete p; } }; template <typename T> struct foo : foobase<T> { T& operator*() const { return *p; } }; template<> struct foo<void> : foobase<void> { };
Вот так:
template<typename T> struct foo_base { T* p; foo(T* x) : p(x) {} ~foo() { if(p) delete p; } // other methods … }; template<typename T> struct foo : foo_base<T> { T& operator*() const { return *p; } }; template<> struct foo<void> : foo_base<void> { };
Как насчет
typename disable_if<is_void<T>, T>::type& operator* () const { return *p;}
Или я упускаю что-то очевидное?
Что насчет этого решения:
template<typename T> struct foo { T* p; foo(T* x) : p(x) {} ~foo() { if(p) delete p; } template<typename U> struct impl { U& deref(U* p) { return *p; } }; template<> struct impl<void> { void deref(void* p) { } }; typename boost::conditional<std::is_void<T>::value, T, typename std::add_reference<T>::type>::type operator*() const { static_assert(!std::is_void<T>::value, "illegal use of type 'void'"); return impl<T>().deref(p); } };