Использование безымянного пространства имен для переопределения класса друга в API и доступа к закрытым членам?

Я пытаюсь получить доступ к некоторым закрытым членам класса, который является частью API, который я не могу изменить.

Листинг 1: api.h

namespace api {
    class Bar;

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

Листинг 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;
}

Это прекрасно компилируется (и работает) в Oracle Solaris Studio 12.3, но clang и g++ (по понятным причинам) имеют проблемы с этим:

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

Этот хакер в настоящее время используется ради эффективности, с хорошим знанием того, как класс работает внутри. Есть ли способ добиться такого же трюка в clang, чтобы я мог изменить значение класса друга только для моей единицы перевода?

Или, если это не удастся, любой трюк, который позволяет мне получить доступ к приватному члену в классе, где я не могу изменить объявления, будет принят!

1 ответ

Решение

Как прокомментировано в посте вопроса, я не знаю, как решить эту проблему с пространством имен. Но, по просьбе автора, any trick that lets me access a private member in a class where I cannot modify the declarations would be appreciated!... вот мой трюк:

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

Это ужасно, но если вы знаете, что делаете, это сделает общедоступными все закрытые члены, объявленные в классах "api.h" (+ все остальные классы, возможно, объявленные в файлах, включая "api.h")!

Другие вопросы по тегам