Наверное, у каждого бывали в жизни случаи, когда очень хотелось получить несанкционированный доступ к закрытым членам какого-то класса. Ну вот понимаешь, что нельзя, но очень хочется. А знаете ли вы, что это можно сделать абсолютно легально и в соответствии со стандартом С++? Ну, кто-то знает, а кто-то нет. Фокус в том, что существует один сценарий, когда мы имеем полное право использовать имя закрытого члена класса. Это случай явного инстанцированя какого-нибудь шаблона:
17.7.2 Explicit instantiation12 The usual access checking rules do not apply to names used to specify explicit instantiations.
То есть мы можем обращаться к закрытому члену класса при явном инстанцировании какого-нибудь шаблона, параметром которого является этот член. Таким образом, задача сводится к тому, чтобы, при инстанцированиии шаблона класса, сохранить значение его определенного параметра, имеющего тип указателя на член, в определенную статическую переменную такого же типа. Добавляем синтаксического сахарку и дело, как говорится, в шляпе.
Здравствуйте, Nikе, Вы писали:
_>>Image: 2013_09_10_12_12_allunix_ru_back_screamingrobot.jpg N>А почему бы и нет?
Новый тренд: русские программисты (на манер британских учоных)
Когда им нечем заняться, они придумывают публичный доступ к закрытым данным.
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, Vain, Вы писали:
N>>А почему бы и нет? V>Новый тренд: русские программисты (на манер британских учоных) V>Когда им нечем заняться, они придумывают публичный доступ к закрытым данным.
Russian hackers, sir.
И каждый день — без права на ошибку...
Re: [Trick] Легальный способ доступа к закрытым членам
Хотелось бы тут выводить типы A и int автоматически.
R>ENABLE_PIVATE_MEMBER_ACCESS(A_value, A, int, m_value)
Использование decltype в специализации компилируется, но любые попытки использовать дальше не увенчались успехом.
Есть идеи ?
template<typename MemberPtrT, MemberPtrT>
struct X;
template<> struct X<decltype(&A::m_value), &A::m_value> // : Base<decltype(&A::m_value)> // нет доступа
{
// using Q = decltype(&A::m_value); // нет доступа
};
_NN>Использование decltype в специализации компилируется, но любые попытки использовать дальше не увенчались успехом. _NN>Есть идеи ?
Убил на это уйму времени, результат — ноль
Я пробовал обеспечить доступ через дружественные фунции. На msvc работает, на gcc — нет. Причем, gcc прав
P.S. Кстати, если бы это удалось сделать, то одновремено с этим получилось бы сделать указатель на член constexpr, а не защелкивать его в runtime переменной, как сейчас.
Здравствуйте, rg45, Вы писали:
R>Я пробовал обеспечить доступ через дружественные фунции. На msvc работает, на gcc — нет. Причем, gcc прав
Где код ?
Может получиться что-нибудь придумать.
R>P.S. Кстати, если бы это удалось сделать, то одновремено с этим получилось бы сделать указатель на член constexpr, а не защелкивать его в runtime переменной, как сейчас.
Здравствуйте, _NN_, Вы писали:
R>>Я пробовал обеспечить доступ через дружественные фунции. На msvc работает, на gcc — нет. Причем, gcc прав
_NN>Где код ? _NN>Может получиться что-нибудь придумать.
Не сохранился, восстановлю, как появится свободная минутка. Идея основывается на том, что в некоторых случаях ADL заглядывает внутрь классов в поисках дружественных функций. Только по стандарту, это делается только в том случае, если в сигнатуре функции присутствует какая-то связь с классом, дружественной которому эта функция является. gcc постуает строго, как написано в стандарде. А msvc более "либеральна" в этом плане. Таким образом нужный указатель на член можно запаковать в тип возвращаемого значения, а потом вытащить его при помощи внешней метафункции.
--
Re: [Trick] Легальный способ доступа к закрытым членам
Здравствуйте, rg45, Вы писали:
R>Наверное, у каждого бывали в жизни случаи, когда очень хотелось получить несанкционированный доступ к закрытым членам какого-то класса.
Поэтому я по возможности предпочитаю такие приватные поля.
// Public.hstruct Public {
static Public* create(int value);
virtual int getValue() const=0;
virtual ~Public() {}
};
// Public_create.cpp#include"public.h"#include"a_lot_of_trash_and_other_dependencies"struct Private : Public {
int value;
Private(int value) : value(value) {}
int getValue() const { return value; }
};
Public* Public::create(int value) {
return new Private(value);
}
Уменьшается время компиляции и связность, улучшается читаемость и не хочеться несанкционированного доступа
А то что в C++ называется private ниразу не private оно не скрывает реализации просто осложняет доступ.
Зато тянет за собой зависимости связанные с типом приватного поля и его реализацией, чего в большинстве случаев нафиг не упало.
Re[2]: [Trick] Легальный способ доступа к закрытым членам
Здравствуйте, kov_serg, Вы писали:
_>Поэтому я по возможности предпочитаю такие приватные поля. _>Уменьшается время компиляции и связность, улучшается читаемость и не хочеться несанкционированного доступа _>А то что в C++ называется private ниразу не private оно не скрывает реализации просто осложняет доступ. _>Зато тянет за собой зависимости связанные с типом приватного поля и его реализацией, чего в большинстве случаев нафиг не упало.
Я, в общем-то, имею кое-какое представление и о способах сокрытия реализации, и об абстракных классах, их преимуществах и областях применимости. Я только не очень понимаю, зачем ты здесь обо всем этом рассказываешь. Вопрос, по-моему, был поставлен предельно ясно: "кто хочет вишенку, вот вам вишенка". Кто не хочет, тот не ест. Ты же, зачем-то, пытаешься убедить всех, что хотеть вишенку — это плохо, потому, что на Луне вишни не растут
Здравствуйте, rg45, Вы писали:
R>Я, в общем-то, имею кое-какое представление и о способах сокрытия реализации, и об абстракных классах, их преимуществах и областях применимости. Я только не очень понимаю, зачем ты здесь обо всем этом рассказываешь. Вопрос, по-моему, был поставлен предельно ясно: "кто хочет вишенку, вот вам вишенка". Кто не хочет, тот не ест. Ты же, зачем-то, пытаешься убедить всех, что хотеть вишенку — это плохо, потому, что на Луне вишни не растут
Просто так, не обижайся. Я знаю что у вас черный пояс по C++, но нафига такие вишни? Как вообще пришла в голову идея лезть туда где написано не лезь убъёт?
И что мешало просто вместо private просто написать public или define-ом (#define RELEASE_PRIVATE public) это сделать.
Более того что сечас легальный способ в новом стандарте может перейти в разряд UB, что бы не было скучно.
Re[2]: [Trick] Легальный способ доступа к закрытым членам
Здравствуйте, _NN_, Вы писали:
_NN>Использование decltype в специализации компилируется, но любые попытки использовать дальше не увенчались успехом. _NN>Есть идеи ?
_NN>
_NN>template<typename MemberPtrT, MemberPtrT>
_NN>struct X;
_NN>template<> struct X<decltype(&A::m_value), &A::m_value> // : Base<decltype(&A::m_value)> // нет доступа
_NN>{
_NN> // using Q = decltype(&A::m_value); // нет доступа
_NN>};
_NN>
_NN>Где код ? _NN>Может получиться что-нибудь придумать.
Вот, восстановил, все-таки. Это работает на mcvc, но не работает на gcc. Ключевой момент в том, что по стандарту хелперная функция не должна в этом случае вноситься в область видимости пространства имен. Но вот на msvc вносится. Э-х-х! сколько клевых фишек можно было бы сделать, будь это стандартым поведением! Синтаксическим сахаром на этор раз не стал особо заморачиваться, ибо все равно не портабельно:
error C3861: 'privateMemerAccessEnablerAux': identifier not found
note: 'privateMemerAccessEnablerAux': function was not declared in the template definition context and can be found only via argument-dependent lookup in the instantiation context
note: see reference to alias template instantiation 'PrivateMemberAccess<A_value>' being compiled
_NN>error C3861: 'privateMemerAccessEnablerAux': identifier not found
_NN>note: 'privateMemerAccessEnablerAux': function was not declared in the template definition context and can be found only via argument-dependent lookup in the instantiation context
_NN>note: see reference to alias template instantiation 'PrivateMemberAccess<A_value>' being compiled
Ну, ожидаемо, в принципе. Они часто запаздывают, но рано или поздно чинят.
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, ViTech, Вы писали:
_NN>В том и дело, что в специализации можно использовать decltype, но за пределами уже нельзя. _NN>Например тут как добраться до MemberPtr ?
Я показал способы, как добраться до decltype(&A::m_value) внутри специализации. Действительно, толку от этого мало, потому как тип нужен снаружи. Надо думать, как отвязаться от зависимости decltype(&A::m_value) в параметре шаблона после того, как доступ к нему получен. Может что-то в таком ключе:
Может в какую-нибудь статическую переменную указатель сохранить (как pointerToMember в начальном примере). Но для этого тоже тип нужен, если только void* не использовать .
_NN>X<decltype(&A::m_value)::MemberPtr не скомпилируется.
И правильно сделается, а то слишком просто было бы .
Во всей этой истории мне интересно, зачем в стандарте такое исключение сделали. Явно не для того, чтоб кто угодно мог по приватным данным шарить. Предполагаю, это нужно, чтобы была возможность специализировать шаблоны для типов из приватных секций(чтоб костыли не писать и в публичных секциях эти типы показывать). Соответственно, пользоваться этими специализациями могут только те, у кого есть доступ к приватным типам, а не все подряд. Есть ещё мысли на этот счёт?
Пока сам не сделаешь...
Re[5]: [Trick] Легальный способ доступа к закрытым членам
Собрав всё воедино получилось вытащить тип и указатель на член наружу.
Получилось вытащить смещение от начала класса, что в принципе должно быть достаточно, чтобы получить доступ.
Осталось понять получить всё во времени компиляции.
Здравствуйте, _NN_, Вы писали:
_NN>Собрав всё воедино получилось вытащить тип и указатель на член наружу.
_NN>Получилось вытащить смещение от начала класса, что в принципе должно быть достаточно, чтобы получить доступ. _NN>Осталось понять получить всё во времени компиляции.
Ну так пока что только смещение и удалось вытащить, ну а что дальше? Чтобы получить-таки доступ к члену, придется использовать принудительное преобразование к нужному типу, который указывать, опять же, придется вручную. Ведь decltype(&A::value) здесь снова не прокатит. Или я чего-то не понял?
--
Re[7]: [Trick] Легальный способ доступа к закрытым членам
Здравствуйте, rg45, Вы писали:
R>Ну так пока что только смещение и удалось вытащить, ну а что дальше? Чтобы получить-таки доступ к члену, придется использовать принудительное преобразование к нужному типу, который указывать, опять же, придется вручную. Ведь decltype(&A::value) здесь снова не прокатит. Или я чего-то не понял?