Skip to content

Instantly share code, notes, and snippets.

@wholivesinapineappleunderthesea
Created May 23, 2024 15:24
Show Gist options
  • Save wholivesinapineappleunderthesea/5a2e4b3220ec63f653a2d212cee5a73f to your computer and use it in GitHub Desktop.
Save wholivesinapineappleunderthesea/5a2e4b3220ec63f653a2d212cee5a73f to your computer and use it in GitHub Desktop.
// https://web.archive.org/web/20120401132446/http://bloglitb.blogspot.com/2011/12/access-to-private-members-safer.html
// This technique was invented by litb in 2010, long before
// templates were supercharged in C++17. Inspired by this method, I have
// reimplemented it using more modern C++ features.
//
// https://www.youtube.com/watch?v=SmlLdd1Q2V8
/*
14.7.2p8 The usual access checking rules do not apply to names used to specify
explicit instantiations. [Note: In particular, the template arguments and names
used in the function declarator (including parameter types, return types and
exception specifications) may be private types or objects which would normally
not be accessible and the template may be a member template or member function
which would not normally be accessible.]
*/
namespace
{
// When explicitly instantiated, this assigns a non-type-template-parameter
// value to a reference during global initialization
template <auto& Where, auto What>
requires std::convertible_to<decltype(Where), decltype(What)>
struct NTTPAssigner
{
static inline decltype(auto) s_assignmentReturnResult{Where = What};
};
// int PrivateClass::*i_privateClassBPointer{};
// template struct NTTPAssigner<i_privateClassBPointer, &PrivateClass::b>;
// Effectively, this is roughly equivalent to:
// int PrivateClass::*i_privateClassBPointer = &PrivateClass::b;
// CSimpleSprite:
// float m_xpos;
float CSimpleSprite::*i_CSimpleSpriteMemberPointerMXPos{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMXPos,
&CSimpleSprite::m_xpos>;
// float m_ypos;
float CSimpleSprite::*i_CSimpleSpriteMemberPointerMYPos{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMYPos,
&CSimpleSprite::m_ypos>;
// float m_angle;
float CSimpleSprite::*i_CSimpleSpriteMemberPointerMAngle{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMAngle,
&CSimpleSprite::m_angle>;
// float m_scale;
float CSimpleSprite::*i_CSimpleSpriteMemberPointerMScale{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMScale,
&CSimpleSprite::m_scale>;
// float m_points[8];
float (CSimpleSprite::*i_CSimpleSpriteMemberPointerMPoints)[8]{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMPoints,
&CSimpleSprite::m_points>;
// float m_uvcoords[8];
float (CSimpleSprite::*i_CSimpleSpriteMemberPointerMUVCoords)[8]{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMUVCoords,
&CSimpleSprite::m_uvcoords>;
// float m_red;
float CSimpleSprite::*i_CSimpleSpriteMemberPointerMRed{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMRed,
&CSimpleSprite::m_red>;
// float m_green;
float CSimpleSprite::*i_CSimpleSpriteMemberPointerMGreen{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMGreen,
&CSimpleSprite::m_green>;
// float m_blue;
float CSimpleSprite::*i_CSimpleSpriteMemberPointerMBlue{};
template struct NTTPAssigner<i_CSimpleSpriteMemberPointerMBlue,
&CSimpleSprite::m_blue>;
}; // namespace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment