#опытным
Спасибо @d7d1cd за идею для поста)
В любой системе есть дырки, которые могут(и обязательно будут) эксплуатировать заинтересованные люди. Вот и в С++ так же. Сегодня мы раскроем, как можно стандартными относительно неинвазивными(не изменяя первоначальный код класса) инструментами изменять приватные поля класса.
Возьмем простой класс:
class X {
public:
X() : private_(1) {}
template <class T>
void f(const T &t) {}
int Value() { return private_; }
private:
int private_;
};Чтобы трюк сработал, в классе должен быть шаблонный метод.
Теперь следите за руками.
Стандарт говорит, что вы самые хамские-хамы, если пытаетесь получить доступ к непубличным членам и будете за это жестко наказаны. Они должны быть использованы только внутри методов класса.
Дак, мы и не против. Давайте просто впишем новый метод класса, где изменим приватное поле, как нам нужно. И для этого даже не нужно менять код класса. И ключ ко всему - шаблонный метод.
Мы можем вне класса специлизировать шаблон метода для работы с конкретным типом. Специализация шаблона метода - это такой же метод с такими же правами, он может получать доступ к непубличным полям.
И тогда класс будет себя вести именно так, как мы ему скажем. А скажем мы ему пару ласковых:
struct Y {};
template <>
void X::f(const Y &) {
private_ = 2;
}
int main() {
X x;
std::cout << x.Value() << std::endl; // prints 1
x.f(Y());
std::cout << x.Value() << std::endl; // prints 2
}В специализированном методе мы изменяем приватное поле и для наглядности выводим значение приватного поля в консоль. Можете сами убедиться, что это работает.
Этот трюк был описан Гербом Саттером, поэтому и называется Sutter hack.
Однако с его помощью нельзя менять поведение стандартных объектов:
The behavior of a C++ program is undefined if it declares
- an explicit specialization of any member function of a standard library class template, or
- an explicit specialization of any member function template of a standard library class or class template, or
- an explicit or partial specialization of any member class template of a standard library class or class template, or
- a deduction guide for any standard library class template.
потому что явные специализации методов из STL приводят к ub.
В общем, интересно, как на стыке двух концепций - ООП и шаблонов - появляются такие интересные спецэффекты)
Hack the life. Stay cool.
#cppcore #template #fun