Workaround for using a private struct - c++

I am using an engine for my console application. This engine can not be changed. The engine contains a class called Mesh. There's a public method in this class findBoundaryLoops() which I'm using in my class (which is not part of the engine) but I have to pass a parameter to this method which type VertexLoop is defined as a private attribute. I'm not sure that I explain it well, so there's a representation of the code:
Mesh.h:
class Mesh final
{
private:
...
struct VertexNode
{
Edge connectingEdgeWithNext;
Vertex vertex;
VertexNode* prev;
VertexNode* next;
float angle;
};
struct VertexLoop
{
VertexNode* firstNode;
uint32_t nodeCount;
template<typename Callable>
void forEachNode(Callable&& f)
{
VertexNode* n = firstNode;
for (uint32_t i = 0; i < nodeCount; ++i, n = n->next)
{
f(n);
}
}
};
...
public:
...
void findBoundaryLoops(memory::MemoryArena& arena, vector<VertexLoop>& loops) const;
...
};
I have to use the findBoundaryLoops() method, but the VertexLoop struct is private. Is there a workaround or something to solve this problem?

This answer has two parts. Below I will show you how to access the type declared in the private section. But I think the important point, and thats why I put it first, is to realize that you should not need the below solution. Anybody can access VertexLoop. The name is private the type not. There was no point to declare it in the private section in the first place. If the type appears on the signature of a public method you can as well put it in the public section.
If this is library code or generated code, then either you misunderstand how to use it, or it can be considered broken.
Simpler example:
#include <vector>
struct foo {
private:
struct bar{};
public:
void f(std::vector<bar>&){}
};
Now we write a trait that given a member function of foo with a single vector parameter tells us the value_type of that vector. Then we instantiate it with a pointer to foo::f to get an alias to bar:
template <typename X>
struct bar_type;
template <typename T> struct bar_type< void(foo::*)(std::vector<T>&)> { using type = T; };
using public_bar = bar_type<decltype(&foo::f)>::type;
Using it:
int main() {
std::vector<public_bar> v;
foo f;
f.f(v);
}
Live Demo
Maybe worth to note that this is by no means comparable to "dirty hacks" by which one can access private members of a class (yes they do exist). This is not a hack, it is perfectly fine partial specialization of a trait to get the parameter type of a public method.
TL;DR Just don't do it. Move VertexLoop to the public section.

Related

Is there a way of using an anonymous class in a typedef?

Consider
template<class Base> struct ChildT : Base
{
};
struct NoBase{};
typedef ChildT<NoBase> Child;
Is there a way of writing this typedef so you don't need to define NoBase? I'm thinking of something like the following:
typedef ChildT<class {}> Child;
There's std::monostate, which is defined just like your NoBase.
As you can see from the link it is not been thought for your use case, but essentially it can. After all, it's just a unit type.
I'm not sure whether std::monostate is the only empty struct in the STL. Nothing comes to mind, except std::nullptr_t, which however is not defined as struct nullptr_t {} but as decltype(nullptr), so it is not an alternative to std::monostate.
I would do it like this :
namespace details
{
struct none
{
};
}
template<typename Base = details::none>
struct ChildT :
public Base // be sure to use the correct inheritance, private is default
{
void do_something() {}
};
using Child = ChildT<>;
int main()
{
Child c;
c.do_something();
}
Note : after reading the other answers std::monostate does the same as details::none :)

Is it relevant to use nested struct?

I'm trying to define a class that has private struct and public struct.
Private struct is the struct that will only be used by the class (e.g. SNode), and I don't want it to be visible outside the class because I don't want it to be mistakenly used (e.g. new Node()). Thus, I reached to the idea to set it basically hidden.
Public struct is the struct that will be used outside (e.g. SKeyValuePair), and it will have a pointer to a SNode.
Code Example is below.
[Class Definition]
template <typename T>
class A
{
private:
struct SNode
{
SNode* pParentNode;
SNode* pLeftChildNode;
SNode* pRightChildNode;
...
};
public:
A<T>()
{
}
virtual ~A()
{
}
struct SPair
{
private:
public:
SNode* pNode;
unsigned long long ullKey;
T value;
...
};
const SPair GetMinKeyPair()
{
return SPair(...);
}
const SPair GetNextMinKeyPair()
{
...
return SPair(...);
}
};
[Usage]
A a;
...
for (A::SPair pair = a.GetMinKeyPair(); pair.pNode != nullptr; pair = a.GetNextMinKeyPair())
{
...
}
Q1. I wonder if this kind of nested struct (which public struct containing private struct pointer) should be avoided for some reason I currently don't know.
Q2. If there are reasons, I wonder what they are.
In general, this is not a bad way to do business.
It keeps the name SNode<T> private when it doesn't need to be public. (Though, as aschepler noted in comments, be aware that the type itself can still be used in full via auto; accessibility affects only names.)
So this is quite a neat way to organise things, and I do personally make use of nested types.
However, since A is a class template, you're going to have a copy of SNode for each T that you use. That's just how templates work. This means more code and a larger executable. For that reason, you might consider the more conventional approach of just putting the utility types in a namespace instead. Does it really matter whether people try to use them outside of A<T>?

Casting an object to a derived class to access protected members of parent class

I'm trying to access a protected member of a class defined and implemented by an external library. I'd like to achieve that without copying or moving the instance if possible.
Here is a simplified example. Let's say this is the code from the external library:
// some_external_library.h
class Node {
public:
static Node Create();
protected:
Node(int val) : val_(val) {}
int val_;
};
This is what I am trying to do:
// my_code.cpp
#include "some_external_library.h"
Node node = Node::Create();
int val = node.val_; // <-- This is invalid since val_ is protected.
Node class is part of some external library that I link to my program. So, I'd like to avoid modifying Node class by adding a public function or friend declaration for accessing val_. Also, I'd like to avoid creating a copy of node object or moving from it, so I'd like to avoid creating a derived class moving/copying the Node instance just to access a member field. Is it possible?
I came up with a possible solution, which worked fine for the minimal example:
// my_code.cpp
#include "some_external_library.h"
class NodeAccessor : public Node {
public:
int val() const { return val_; }
};
Node node = Node::Create();
int val = static_cast<const NodeAccessor&>(node).val();
However, I'm not sure if this is valid since node isn't an instance of NodeAccessor. Is this standard compliant? Would it cause any problems (e.g. optimizing away of val_ during compilation of the external library)?
What you do is UB.
There is one magical way to access private/protected member in C++:
The ISO C++ standard specifies that there is no access check in case of explicit template instantiations, and following code abuse of that:
template <typename Tag>
struct result
{
using type = typename Tag::type;
static type ptr;
};
template <typename Tag> typename result<Tag>::type result<Tag>::ptr;
template<typename Tag, typename Tag::type p>
struct rob : result<Tag> {
/* fill it ... */
struct filler {
filler() { result<Tag>::ptr = p; }
};
static filler filler_obj;
};
template <typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;
And then
struct NodeVal { using type = int Node::*; };
template class rob<NodeVal, &Node::val_>;
and finally:
int main() {
Node node = /**/;
(node.*result<NodeVal>::ptr);
}
Demo
Yes, that can and will and should cause problems.
You are casting a thing to a type, then the thing is not of that type.
All manner of antics can ensue as a result.
There is simply no way to do what you're trying to do, and that's a good thing! Access protections are there for a reason. Work with them, not against them.

Allowing access to private members

This question is somewhat a continuation of this one I've posted.
What I was trying to do: my point was to allow access to private members of a base class A in a derived class B, with the following restraints:
what I want to access is a structure -- an std::map<>, actually --, not a method;
I cannot modified the base class;
base class A has no templated method I may overload as a backdoor alternative -- and I would not add such method, as it would be going against the second restraint.
As a possible solution, I have been pointed to litb's solution (post / blog), but, for the life of me, I haven't been able to reach an understanding on what is done in these posts, and, therefore, I could not derive a solution to my problem.
What I am trying to do: The following code, from litb's solution, presents an approach on how to access private members from a class/struct, and it happens to cover the restrictions I've mentioned.
So, I'm trying to rearrange this one code:
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
// use
struct A {
A(int a):a(a) { }
private:
int a;
};
// tag used to access A::a
struct A_f {
typedef int A::*type;
friend type get(A_f);
};
template struct Rob<A_f, &A::a>;
int main() {
A a(42);
std::cout << "proof: " << a.*get(A_f()) << std::endl;
}
To something that would allow me to do the following -- note I'm about to inherit the class, as the entries in the std::map<> are added right after the initialization of the derived class B, i.e., the std::map<> isn't simply a static member of class A with a default value, so I need to access it from a particular instance of B:
// NOT MY CODE -- library <a.h>
class A {
private:
std::map<int, int> A_map;
};
// MY CODE -- module "b.h"
# include <a.h>
class B : private A {
public:
inline void uncover() {
for (auto it(A_map.begin()); it != A_map.end(); ++it) {
std::cout << it->first << " - " << it->second << std::endl;
}
}
};
What I'd like as an answer: I'd really love to have the above code working -- after the appropriate modifications --, but I'd be very content with an explanation on what is done in the first code block -- the one from litb's solution.
The blog post and its code is unfortunately a bit unclear. The concept is simple: an explicit template instantiation gets a free backstage pass to any class, because
An explicit instantiation of a library class may be an implementation detail of a client class, and
Explicit instantiations may only be declared at namespace scope.
The natural way to distribute this backstage pass is as a pointer to member. If you have a pointer to a given class member, you can access it in any object of that class regardless of the access qualification. Fortunately, pointer-to-members can be compile-time constants even in C++03.
So, we want a class which generates a pointer to member when it's explicitly instantiated.
Explicit instantiation is just a way of defining a class. How can merely generating a class do something? There are two alternatives:
Define a friend function, which is not a member of the class. This is what litb does.
Define a static data member, which gets initialized at startup. This is my style.
I'll present my style first, then discuss its shortcoming, and then modify it to match litb's mechanism. The end result is still simpler than the code from the blog.
Simple version.
The class takes three template arguments: the type of the restricted member, its actual name, and a reference to a global variable to receive a pointer to it. The class schedules a static object to be initialized, whose constructor initializes the global.
template< typename type, type value, type & receiver >
class access_bypass {
static struct mover {
mover()
{ receiver = value; }
} m;
};
template< typename type, type value, type & receiver >
typename access_bypass< type, value, receiver >::mover
access_bypass< type, value, receiver >::m;
Usage:
type_of_private_member target::* backstage_pass;
template class access_bypass <
type_of_private_member target::*,
& target::member_name,
backstage_pass
>;
target t;
t.* backstage_pass = blah;
See it work.
Unfortunately, you can't rely on results from this being available for global-object constructors in other source files before the program enters main, because there's no standard way to tell the compiler which order to initialize files in. But globals are initialized in the order they're declared, so you can just put your bypasses at the top and you'll be fine as long as static object constructors don't make function calls into other files.
Robust version.
This borrows an element from litb's code by adding a tag structure and a friend function, but it's a minor modification and I think it remains pretty clear, not terribly worse than the above.
template< typename type, type value, typename tag >
class access_bypass {
friend type get( tag )
{ return value; }
};
Usage:
struct backstage_pass {}; // now this is a dummy structure, not an object!
type_of_private_member target::* get( backstage_pass ); // declare fn to call
// Explicitly instantiating the class generates the fn declared above.
template class access_bypass <
type_of_private_member target::*,
& target::member_name,
backstage_pass
>;
target t;
t.* get( backstage_pass() ) = blah;
See it work.
The main difference between this robust version and litb's blog post is that I've collected all the parameters into one place and made the tag structure empty. It's just a cleaner interface to the same mechanism. But you do have to declare the get function, which the blog code does automatically.
OK, so you asked about how to make that weird "Rob" code work with your use case, so here it is.
// the magic robber
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
// the class you can't modify
class A {
private:
std::map<int, int> A_map;
};
struct A_f {
typedef std::map<int, int> A::*type;
friend type get(A_f);
};
template struct Rob<A_f, &A::A_map>;
class B : private A {
public:
inline void uncover() {
std::map<int, int>::iterator it = (this->*get(A_f())).begin();
}
};
Now, I personally think the cure here may be worse than the disease, despite that I'm usually the last one you'll see claiming that abusing C++ is OK. You can decide for yourself, so I've posted this as a separate answer from my one using the preprocessor to do it the old-school way.
Edit:
How It Works
Here I will replicate the code above, but with the types simplified and the code drawn out more, with copious comments. Mind you, I did not understand the code very well before I went through this exercise, I don't understand it completely now, and I certainly won't remember how it works tomorrow. Caveat maintainer.
Here's the code we aren't allowed to change, with the private member:
// we can use any type of value, but int is simple
typedef int value_type;
// this structure holds value securely. we think.
struct FortKnox {
FortKnox() : value(0) {}
private:
value_type value;
};
Now for the heist:
// define a type which is a pointer to the member we want to steal
typedef value_type FortKnox::* stolen_mem_ptr;
// this guy is sort of dumb, but he knows a backdoor in the standard
template<typename AccompliceTag, stolen_mem_ptr MemPtr>
struct Robber {
friend stolen_mem_ptr steal(AccompliceTag) {
return MemPtr; // the only reason we exist: to expose the goods
}
};
// this guy doesn't know how to get the value, but he has a friend who does
struct Accomplice {
friend stolen_mem_ptr steal(Accomplice);
};
// explicit instantiation ignores private access specifier on value
// we cannot create an object of this type, because the value is inaccessible
// but we can, thanks to the C++ standard, use this value in this specific way
template struct Robber<Accomplice, &FortKnox::value>;
// here we create something based on secure principles, but which is not secure
class FortKnoxFacade : private FortKnox {
public:
value_type get_value() const {
// prepare to steal the value
// this theft can only be perpetrated by using an accomplice
stolen_mem_ptr accessor = steal(Accomplice()); // it's over now
// dereference the pointer-to-member, using this as the target
return this->*accessor;
}
};
int main() {
FortKnoxFacade fort;
return fort.get_value();
}
How about something more brutal?
// MY CODE -- module "b.h"
# define private protected
# include <a.h>
# undef private
class B : private A {
// now you can access "private" members and methods in A
The best-packaged version I know of this idiom is as follows:
template<class Tag,typename Tag::type MemberPtr>
struct access_cast{
friend typename Tag::type get(Tag){return MemberPtr;};
};
template<class Tag,class MemberPtr>
struct access_tag{
typedef MemberPtr type;
friend type get(Tag);
};
class A {
public:
auto x() const {return x_;};
private:
int x_ = 9;
};
#include <iostream>
struct AMemTag: access_tag<AMemTag,int A::*>{}; //declare tag
template struct access_cast<AMemTag,&A::x_>; //define friend get function
int main() {
A a;
std::cout<<a.x()<<"\n";
a.*get(AMemTag()) = 4; //dereference returned member pointer and modify value
std::cout<<a.x()<<"\n";
}
See it work.

How to use policy-templates if the types of two templates are linked?

I'm currently writing a class which allows getting and setting interal program options and it should be quite flexible and easy to use.
Specifically, an option is identified by an enum type and a value type, which have a one-on-one relationship. For example, an enum IntType will contains options which have an int type.
I had in mind the following code, but have no idea how to get it working or whether I'm trying to use templates in a way i shouldn't.
enum IntType {OPTION1, OPTION2}
enum StringType { OPTION3, OPTION4}
template<class T, class T2>
class Policy{
public:
T2 getValue(const T& a);
void setValue(const std::string& name, const T2& a);
...
}
class A: public Policy<IntType, int>, public Policy<Stringtype, std::string>, ...{
...
}
Each enum constant has one associated string representation, which is constant, but options are also taken as string input into the program, so I have to be able to deduce from a string which option I should change.
But obviously, this code cannot be used to directly call set or get values without qualifying its full template specialization. So
A* a = ...
a->setValue("intoption", 5);
will not work.
Any pointers on what I should use to get this working?
A partial answer on how to derive at compile time that OPTION1 maps to int and IntType, ... would also be great.
Thanks in advance,
Broes
It is not necessary to pass both the Enum and the type. You can deduce the enum value from the type itself thanks to a traits class:
template <typename T>
struct PolicyTraits;
template <>
struct PolicyTraits<int> { static Enum const value = IntType; }
// ... and so on ...
Your selection is obviously a bit more difficult. For templates to work correctly you need selection based on compile constants, be they constants or types. This requires the names of your options to be constants.
A revised implementation would thus be:
template<class Name, class Type>
class Policy{
public:
Type getValue(Name);
void setValue(Name, Type const&);
...
}
This can be used as:
struct IntOption {};
class A: public Policy<IntOption, int> {};
int main() {
A a;
a.setValue(IntOption(), 3);
}
Also, you might be interested in looking up How Boost does it and perhaps use their library.
Since you are filling the data at runtime, templates are not viable for this design. Runtime polymorphism with virtual function will be a good choice. For example,
class Options; // Say this is the class of interest
class DataType {
public:
virtual Options& getOptions () = 0;
};
class IntType : public DataType {
public:
Options& getOptions (); // implement for 'int' type
};
class StringType : public DataType {
public:
Options& getOptions (); // implement for 'std::string' type
};
Now, class A should contain a pointer to DataType;
class A {
DataType *pData;
public:
void setValue (DataType *p) { pData = p; }
...
};
Usage:
A *a = ...;
a->setValue(new IntType); // take care of heap allocation / stack allocation