В качестве упражнения для понимания C ++ 0x я пытаюсь создать класс C ++, который оборачивает указатель некоторого типа шаблона:
template <typename T>
class Wrapper {
T *t;
/* ... */
};
Внутри класса Wrapper я хотел бывыставить любые перегруженные операторы, которые T может реализовать через класс Wrapper.Сама оболочка просто перенаправляет вызов функции в базовый объект t.
template <typename U>
auto operator+(U &u) -> decltype (*t + u) {
return *t + u;
}
Подвох состоит в том, что я не хочу, чтобы операторы обертывания выставляли, которые T может не реализовать.Например, если T не реализует operator +, то Wrapper также не должен выставлять operator +.
В случае operator + (и любой двоичной операции) все работает, потому что оператор обязательно становится функцией шаблона и поэтомусоздается только тогда, когда мы пытаемся вызвать, например, Wrapper :: operator +.
Однако в случае унарных операторов (например, ++) нет четкого способа защитить оператор, чтобы онсоздается тогда, когда T реализует оператор ++.Например, наивная реализация оператора ++ в этом классе
auto operator++() -> decltype(++(*t)) {
return ++(*t);
}
не компилируется для T, который не поддерживает оператор ++ ().
Из моего понимания стандарта, если мы имеемследующий код, который использует Wrapper
class X { };
Wrapper<X> w;
Мы создадим экземпляр Wrapper и объявление Wrapper :: operator ++ (), но не его определение , если мы не вызовем его (или явно создать его экземпляр).Обычно это было бы нормально, потому что использование X :: operator ++ происходит только в определении Wrapper :: operator ++ ().Однако из-за decltype мы используем X :: operator ++ в объявлении, так что проверка типов проверяет наличие X :: operator ++ и, таким образом, завершается неудачей.
Можем ли мы определить оператор ++ () (и вообще любойфункция пересылки, которая использует decltype) со свойством, для которого она создается, если базовый объект также поддерживает operator ++ ()?Или, учитывая семантику создания шаблона вместе с decltype, это невозможно сделать?