0

I'm trying to access some private members of a class that's part of an API that I do not have the ability to change.

Listing 1: api.h

namespace api {
    class Bar;

    class Foo {
    public:
        const int& getSecret() const { return secretValue; }
    private:
        int secretValue;
        friend class Bar;
    };
}

Listing 2: program.cpp

#include <iostream>
#include "api.h"

namespace {
    class api::Bar {
        public:
            void touchFooSecretly(api::Foo& f) { f.secretValue = 42; }
    };
}

int main() 
{
    api::Foo f;
    api::Bar b;

    b.touchFooSecretly(f);

    std::cout << f.getSecret() << std::endl; // 42 (Solaris)
    return 0;
}

This compiles (and runs) fine in Oracle Solaris Studio 12.3, but clang and g++ (understandably) have a problem with it:

program.cpp:5:13: error: cannot define or redeclare 'Bar' here because namespace '' does not enclose namespace 'api'

This hack is currently being employed for the sake of efficiency, with good knowledge of how the class operates internally. Is there a way to achieve a similar trick in clang such that I can change the meaning of a friend class for my translation unit alone?

Or, failing that, any trick that lets me access a private member in a class where I cannot modify the declarations would be appreciated!

AstroCB
  • 12,337
  • 20
  • 57
  • 73
Dragos
  • 498
  • 4
  • 13
  • 2
    So you want to have multiple different definitions of `Bar` throughout the program? If so, even if you succeed to compile it, the behaviour will be undefined. – Anton Savin Nov 08 '14 at 08:38
  • My translation unit will have my definition of Bar and the rest of the application will remain unaffected (as it has already been compiled and linked). I think that's well-defined but maybe I'm wrong. – Dragos Nov 08 '14 at 08:42
  • 1
    Another hack is to add `#define private public` before `#include "api.h"` and `#undef private` after. It's awful, but then secretValue will become public...and this will most likely compile with any compiler ;-) – jpo38 Nov 08 '14 at 12:25
  • @jpo38 That's brilliant, never thought to do something so crazy. Thanks for trying to answer the question - feel free to post as an answer and I can accept it if it really is the only work-around. – Dragos Nov 08 '14 at 14:00
  • @Dragos You are welcome, good to know it helps. However, I cannot post this as an answer because it does not answer your original question (and too many downvoters are waiting for me to do it...;-). Please add to your question something like "Any other solution helping me to access secretValue private attribute is acceptable", and then I can post my answer ;-) – jpo38 Nov 08 '14 at 20:08
  • @jpo38 Yes, I was rather looking forward to downvoting your answer for trying to help :P ... anyway, edit done. Thanks. – Dragos Nov 10 '14 at 09:11

1 Answers1

1

As commented in the question's post, I don't know how to fix this namespace problem. But, as requested by the author, any trick that lets me access a private member in a class where I cannot modify the declarations would be appreciated!...here is my trick:

#define private public
#include "api.h"
#undef private

That's awful, but if you know what you are doing, this will make all private members declared in classes of "api.h" (+ all others classes possibly declared in files includes by "api.h") be public!

jpo38
  • 20,821
  • 10
  • 70
  • 151