Clarification: This question originally came from a challenge I thought of, and isn't connect with programming for real systems.
Suppose I have a class, that I know its' architecture which I can't change, and I don't want to inherit it, but I do want to get access to its' private data and functions. How can I do it?
Suppose my class looks like this one:
class A {
public:
int v = 89;
private:
int a = 5;
virtual void function(int a, int b) {
cout << a << " " << b << endl;
}
};
a while ago stumbled upon a neat template trick to do this on this blog: http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
Do NOT use this in any production code, it is just a educational example !!!
it takes basically leverage of the "private" being ignored on some part of template initialization
template<typename Tag>
struct result {
/* export it ... */
typedef typename Tag::type 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;
usage: take following struct:
struct A {
private:
void f() {
std::cout << "proof!" << std::endl;
}
};
create your "robber"
struct Af { typedef void(A::*type)(); };
template class rob<Af, &A::f>;
use it:
int main()
{
A a;
(a.*result<Af>::ptr)();
return 0;
}
A less risky hack will be to make your function/class a friend of the class if you are allowed to modify just the header file.
// Add
class HackA;
class A {
public:
// Add
friend class HackA;
int v = 89;
private:
int a = 5;
virtual void function(int a, int b) {
cout << a << " " << b << endl;
}
};
Now you can use:
class HackA {
public:
int number(A const& a) { return a.v; }
int another_number(A const& a) { return a.a; }
void target_function(A& a, int number, int another_one)
{
a.function(number, another_one);
}
};
int main()
{
A a;
HackA hacker
cout << hacker.number(a) << " " << hacker.another_number(a) << endl;
hacker.target_function(a, 9, 3);
return 0;
}
Related
Given the following code:
class A;
struct B {
static void doIt(A* pa);
};
struct C {
static void doIt(A* pa);
};
class A {
int i = 9;
// below works but requires a line per each type
friend void B::doIt(A* pa);
friend void C::doIt(A* pa);
// the below however doesn't work
// template<typename T>
// friend void T::doIt(A* pa);
// (gcc error: member 'void T::doIt(A*)' declared as friend before type 'T' defined)
// (clang just ignores the above and the error is on accessing A::i in B and C)
};
void B::doIt(A* pa) {
cout << pa->i << endl;
}
void C::doIt(A* pa) {
cout << pa->i *2 << endl;
}
int main() {
A a;
B::doIt(&a);
C::doIt(&a);
}
Is it possible to replace the multiple friend declarations to allow all void T::doIt(A* pa) methods access the private members of A?
Trying to instantiate B and C above A doesn't help.
Not exactly what do you asked but... if you templatize the B, C, etc. structs, you can get something similar.
#include <iostream>
class A;
template <std::size_t>
struct X
{ static void doIt(A* pa); };
class A
{
int i = 9;
template <std::size_t I>
friend void X<I>::doIt (A* pa);
};
template <>
void X<0U>::doIt(A* pa)
{ std::cout << pa->i << std::endl; }
template <>
void X<1U>::doIt(A* pa)
{ std::cout << pa->i * 2 << std::endl; }
template <>
void X<2U>::doIt(A* pa)
{ std::cout << pa->i * 3 << std::endl; }
using B = X<0U>;
using C = X<1U>;
using D = X<2U>;
int main() {
A a;
B::doIt(&a);
C::doIt(&a);
D::doIt(&a);
}
I believe something similar to what you desire can be done using CRTP and private/protected virtual inheritance. The code below is only demonstration and definitely needs some work e.g. to not to involve template method friendship:
#include <iostream>
using namespace std;
class base {
protected:
int i = 9;
};
template <class F>
class crtp_base: virtual base { // private inheritance!
template <class T>
friend void F::doIt(T*);
};
template <class... AllF>
struct crtp_bases: crtp_base<AllF>... { };
struct B {
template <class T>
static void doIt(T* pa);
};
struct C {
template <class T>
static void doIt(T* pa);
};
class A: public crtp_bases<B, C> {
};
template <class T>
void B::doIt(T* pa) {
cout << pa->i << endl;
}
template <class T>
void C::doIt(T* pa) {
cout << pa->i * 2 << endl;
}
int main() {
A a;
B::doIt(&a);
//cout << a.i << endl; // error i is private member of 'base'
}
[live demo]
I see no direct way, but one work-around could be declaring one class with several static methods (instead of several classes with one static method) and then declaring this class as friend, like:
...
struct D {
static void doItB(A* pa);
static void doItC(A* pa);
};
class A {
...
friend struct D;
...
};
void D::doItB(A* pa) {
cout << pa->i << endl;
}
...
D::doItB(&a);
D::doItC(&a);
...
I need to assign unique integer value to each descendant of class Base that should be accessible by using pointer to those classes or its typenames.
I implemented it such way
class Base {
public:
int idCompType = InvalidCompType;
virtual int getCompType() = 0;
}
then in each descendant of base I should declare idCompType (for templates) and override getCompType (for pointers):
class Real1: public Base {
public:
int idCompType = 1;
int getCompType() override { return idCompType; }
}
now I can find comp type from pointer to base
Base *comp = getComp(...);
std::cout << comp->getCompType();
or using typename in template:
template <typename T>
int getType() {
return T::idCompType;
}
Is there a way to make it even simpler without double declaration idCompType and getCompType() in each descendant class? In Object Pascal I achieved this using virtual static methods, but their are not allowed in C++..
PS: the question is not about virtual static methods - virtual static method is just the one of the possible solutions and the way my problem was solved in other language.
My recommendation:
Changes to Base:
class Base {
public:
virtual int getCompType() = 0;
protected:
static int getNextCompType()
{
static int nextType = 0;
return ++nextType;
}
};
Changes to the derived class:
class Real1: public Base {
public:
static int getCompTypeImpl()
{
static int myType = Base::getNextCompType();
return myType;
}
int getCompType() override
{
return getCompTypeImpl();
}
};
Here's a working program:
#include <iostream>
class Base {
public:
virtual int getCompType() = 0;
protected:
static int getNextCompType()
{
static int nextType = 0;
return ++nextType;
}
};
class Real1: public Base {
public:
static int getCompTypeImpl()
{
static int myType = Base::getNextCompType();
return myType;
}
int getCompType() override
{
return getCompTypeImpl();
}
};
class Real2: public Base {
public:
static int getCompTypeImpl()
{
static int myType = Base::getNextCompType();
return myType;
}
int getCompType() override
{
return getCompTypeImpl();
}
};
template <typename T> int getCompType()
{
return T::getCompTypeImpl();
}
int main()
{
Real1 v1;
Real2 v2;
std::cout << v1.getCompType() << std::endl;
std::cout << v2.getCompType() << std::endl;
std::cout << getCompType<Real1>() << std::endl;
std::cout << getCompType<Real2>() << std::endl;
};
Output:
1
2
1
2
Here is a slight variant of #Sahu's version.
Instead of implementing the same getCompTypeImpl() in every derived class, put it in Base class.
template<typename T>
static int getCompTypeImpl()
{
return getNextCompType<T>();
}
Modify getNextCompType() to
template<typename T>
static int getNextCompType()
{
auto iter = m_table.find(std::type_index(typeid(T)));
if (iter != m_table.end())
{
return iter->second;
}
else
{
m_table.insert(std::make_pair(std::type_index(typeid(T)), ++nextType));
return nextType;
}
}
And finally introduce 2 new static data members.
private:
static std::map<std::type_index, int> m_table;
static int nextType;
Please find the full code here.
Admittedly this introduces 2 new static members and does a bit more work
than the original version from Sahu. But, this removes the burden of implementing the methods in
all the derived classes.
Yet another variation of #R Sahu's answer to eliminate duplication of code in the derived classes:
#include <iostream>
class Base {
public:
virtual int getCompType() const = 0;
template <typename T>
static int getCompTypeOf()
{
static int compType = getNextCompType();
return compType;
}
private:
static int getNextCompType()
{
static int nextType = 0;
return ++nextType;
}
};
template <typename Derived, typename DeriveFrom = Base>
class TypeAssigner : DeriveFrom {
public:
int getCompType() const override
{
return Base::getCompTypeOf<Derived>();
}
};
class Real1: public TypeAssigner<Real1> {};
class Real2: public TypeAssigner<Real2> {};
class Real3 : public TypeAssigner<Real3, Real2> {};
int main()
{
Real1 v1;
Real2 v2;
Real3 v3;
std::cout << v1.getCompType() << '\n';
std::cout << v2.getCompType() << '\n';
std::cout << v3.getCompType() << '\n';
std::cout << Base::getCompTypeOf<Real1>() << '\n';
std::cout << Base::getCompTypeOf<Real2>() << '\n';
std::cout << Base::getCompTypeOf<Real3>() << '\n';
};
I have a template method inside a template class.
I read that a method can not be specialized without specialize the class before.
But I want to factorize some of theses methods, is it possible ?
Example :
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num> class A {
private:
num n;
public:
template<typename type>
void multiplyBy(); // by 1 if <int> or 1,5 if <float>
}; // A
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<One>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
template<> template<> void A<Two>::multiplyBy<float>() {
std::cout << 1.5*n.number << std::endl;
}
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
A stackoverflow related question : C++ specialization of template function inside template class
In particular this comment : C++ specialization of template function inside template class
Have I to deduct than there is no way to factorize multiplyBy(), for one for int and an other for float ?
As english is not my natural language maybe I miss something simple, maybe a workaround with partial-specialization.
Edit : put A::n in private to match even better my problem.
You might use tag dispatching:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num>
class A {
public:
num n;
private:
template<typename> struct Tag {};
void multiplyBy(Tag<int>) {
std::cout << 1.0*n.number << std::endl;
}
void multiplyBy(Tag<float>) {
std::cout << 1.5*n.number << std::endl;
}
public:
template<typename type>
void multiplyBy() {
multiplyBy(Tag<type>());
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
But I want to factorize some of theses methods, is it possible ?
You probably know that you cannot use:
template<> template<> void A<One>::multiplyBy<int>() {
std::cout << 1.0*n.number << std::endl;
}
without specializing A<One>.
You can do something along the lines of:
#include <iostream>
class One {
public:
static const int number = 1;
};
class Two {
public:
static const int number = 2;
};
template<typename num, typename type = int> struct MultiplyBy {
static void doit(num n)
{
std::cout << 1.0*n.number << std::endl;
}
};
template<typename num> struct MultiplyBy<num, float> {
static void doit(num n)
{
std::cout << 1.5*n.number << std::endl;
}
};
template<typename num> class A {
public:
num n;
template<typename type>
void multiplyBy()
{
MultiplyBy<num, type>::doit(n);
}
};
int main() {
A<One> aOne;
A<Two> aTwo;
aOne.multiplyBy<int>(); // 1
aOne.multiplyBy<float>(); // 1.5
aTwo.multiplyBy<int>(); // 2
aTwo.multiplyBy<float>(); // 3
return 0;
}
I have a such factories, which instantiate objects by passed template class name T:
template<class T>
class Factory0
{
public:
static void *Create(){ return new T(); }
};
template<class T, class Argument1>
class Factory1
{
public:
static void *Create( Argument1 &arg1 ){ return new T( arg1 ); }
};
And i need to do something like such:
map<string[ClassName], &factory] _builder;
...
template<class T>
Add(){
if( T derived from BaseClass ) _builder[T] = &factory1::Create
else if( T derived from BaseClass ) _builder[T] = &factory0::Create;
}
template<class T>
Create() {
return _builder[T]( (factory0) ? <nothing> : <some_argument> );
}
This is hard for two reasons:
Calling create with the wrong arguments can only be caught at runtime, so we need a bit of dynamic typing.
C++ really doesn't like casting function pointers. Or creating pointers to templated functions. Or generally doing anything complex with function pointers.
But it can be done:
#include<string>
#include<map>
#include<iostream>
using namespace std;
struct returnable {
// Put some interesting virtual functions here
};
struct foo : public returnable {
foo() {
cout << "defaulFoo" << endl;
}
foo(int x) {
cout << "Foo:" << x << endl;
}
};
struct bar : public returnable {
bar(char a, char b){
cout << "bar:" << a << "," << b << endl;
}
};
template<typename... ARGS>
struct newmakerbase {
virtual returnable* make(ARGS... args) = 0;
};
template<typename OUT, typename... ARGS>
struct newmaker : public newmakerbase<ARGS...> {
virtual returnable* make(ARGS... args) {
return new OUT(args...);
}
};
// Boost might provide a neater version of this
int nextId = 0;
template<typename... T>
struct typeId {
static const int id;
};
template<typename... T>
const int typeId<T...>::id = nextId++;
map<string,void*> builders;
map<string,int> argtypes;
template<typename OUT, typename... ARGS>
void registerClas(string name) {
builders[name] = static_cast<void*>(new newmaker<OUT,ARGS...>());
argtypes[name] = typeId<ARGS...>::id;
}
template<typename... ARGS>
returnable* create(string name, ARGS... args) {
int argsgiven = typeId<ARGS...>::id;
if (argsgiven != argtypes[name]) {
// TODO: maybe throw an exception or something?
return NULL;
}
newmakerbase<ARGS...>* builder = static_cast<newmakerbase<ARGS...>*>(builders[name]);
return builder->make(args...);
}
main() {
registerClas<foo>("defaultFoo");
registerClas<foo,int>("foo");
registerClas<bar,char,char>("bar");
returnable* a = create("defaultFoo");
returnable* b = create("foo", 42);
returnable* c = create("foo", 'a', 'b'); // returns NULL
returnable* d = create("foo", 42.0); // also returns NULL
returnable* e = create("bar", 'c', 'd');
cout << a << " " << b << " " << c << " " << d << " " << e << endl;
}
I have a class Foo which uses CRTP to inherit a template method from a parent class and avoid having to provide literally dozens of individual member methods. Something like this:
class Foo : public SomeBarClass<Foo>
{
//..
//from SomeBarClass
public:
template <class T> void onMsg(T* msg);
private:
IFoxMod* foxMod_;
};
Now, in the implementation for onMsg, I would like something like this:
template <class T>
void Foo::onMsg(T* msg)
{
if (foxMod_->shouldDoStuff(msg))
{
//do stuff
}
}
and there can be many foxMod_ types (one of them instantiated in the Foo constructor by name given in config file) as long as they abide by the common interface of providing a bool shouldDoStuff method. The problem, is that this leads me to define the following:
struct IFoxMod
{
virtual ~IFoxMod() {}
template <class T> shouldDoStuff(T* msg) = 0;
};
for all of the FoxMods to implement (like, class redMountainLogic : public IFoxMod might have it's own way of discerning, when it is appropiate to do stuff).
This is illegal though because one cannot have virtual templates and I'm trying to find a workaround for it. Basically, I need to have dynamic dispatch, but the argument I am passing is a template. I can't think of a workaround.
Virtual function tables don't seem to get along well with template specializations. Not too surprising. VFTs are generally based on declaration order, which doesn't really exist with templates. One solution is to manually recreate VFTs.
Here's an example. It could probably be a little cleaner, but it works.
#include<iostream>
using namespace std;
// Message.h
template<int n>
struct MessageByInt {
typedef int Msg;
};
struct MessageOfHope {
int a;
int b;
static const int id = 0;
};
template<> struct MessageByInt<MessageOfHope::id> { typedef MessageOfHope Msg; };
struct MessageOfDoom {
int b;
int c;
static const int id = 1;
};
template<> struct MessageByInt<MessageOfDoom::id> { typedef MessageOfDoom Msg; };
const int nMessages = 2;
// IFoxMod.h
typedef bool(*callback)(void*);
struct IFoxMod {
callback vtable[nMessages];
template<typename MSG>
bool ShouldDoWork(MSG* msg) {
return vtable[MSG::id](msg);
}
};
template<typename TESTER, int n>
struct filler {
typedef typename MessageByInt<n>::Msg MSG;
typedef typename TESTER::template Tester<MSG> Tester;
static void fill(IFoxMod* impl) {
impl->vtable[n] = reinterpret_cast<callback>(&Tester::ReallyShouldDoWork);
filler<TESTER,n-1>::fill(impl);
}
};
template<typename TESTER>
struct filler<TESTER,-1>{
static void fill(IFoxMod* impl) {
}
};
// RedFox.h
struct RedFoxTester {
template<typename MSG>
struct Tester { // This struct exists to allow partial specialization
static bool ReallyShouldDoWork(MSG* msg) {
return msg->b == 2;
}
};
};
struct RedFoxMod : public IFoxMod {
RedFoxMod() {
filler<RedFoxTester,nMessages-1>::fill(this);
}
};
//Main
main() {
IFoxMod* fm = new RedFoxMod();
MessageOfHope mohb2 = {1, 2};
MessageOfDoom modb2 = {2, 3};
MessageOfHope mohbn2 = {2, 3};
MessageOfDoom modbn2 = {1, 2};
cout << fm->ShouldDoWork(&mohb2) << ", " << fm->ShouldDoWork(&modb2) << endl;
cout << fm->ShouldDoWork(&mohbn2) << ", " << fm->ShouldDoWork(&modbn2) << endl;
}