I'm using templates to explicitly declare and allow read access to specific data.
#include <type_traits>
template <typename T>
struct Access
{
template <typename U>
void Read()
{
static_assert(std::is_same_v<T, U>);
}
};
Normally T
would be a set of types, but I've simplified it here.
I'd like to ensure that any access that gets declared actually gets used. If a user declares Access<int>
I want to check to see that there is a corresponding Read<int>
somewhere.
Give that context, what I'm currently trying to do is detect whether Access<int>::Read<int>
ever gets instantiated. Is this possible?
I tried using extern template
to prevent implicit instantiations. The main problem here is that you have to explicitly write out every possible type at namespace scope. I don't see a way to do this systemically.
extern template void Access<int>::Read<int>();
int main()
{
auto IsIntReadUsed = &Access<int>::Read<int>; // Linker error, yay!
return 0;
}
Being able to detect this at compile time, link time, or run time is acceptable. The solution does not need to be portable across compilers. A solution that works on any single compiler is sufficient. Any C++ version is acceptable.
Here is a sandbox for experimenting https://godbolt.org/z/d5cco989v
// -----------------------------------------------------------
// Infrastructure
#include <type_traits>
template <typename T>
struct Access
{
template <typename U>
void Read()
{
static_assert(std::is_same_v<T, U>);
}
};
int main()
{
return 0;
}
// -----------------------------------------------------------
// User Code
using UserAccess = Access<int>;
void UserUpdate(UserAccess access)
{
// Oh no, access.Read<int> is never used!
(void) access;
}
// -----------------------------------------------------------
// Validation
template <typename TDeclared>
void ValidateAccess(Access<TDeclared>)
{
// Write something here that can tell if Access<TDeclared>::Read<TDeclared> has been
// used when this is called with UserAccess (i.e. ValidateAccess(UserAccess())).
// This could also be implemented inside the Access class.
}