Is it possible to generate constant value during compilation? - c++

I would like my classes to be identified each type by an unique hash code. But I don't want these hashed to be generated every time a method, eg. int GetHashCode(), is invoked during runtime. I'd like to use already generated constants and I was hoping there is a way to make the compiler do some come computing and set these constants. Can it be done using templates? Could you give me some example, if it is possible.
UPDATE:
Thanks to kriss' comment I realized my question should go like this:
How to do the type checking with the lowest runtime cost possible?
I'd like to check a pointer to an object against a class type. Just the classes I implement in my libs, so I was thinking of some custom hashing, thus the original question. I did consider using typeid but I am unaware of the runtime cost of using it. I made an assumption that since typeid produces a type_info class that would be more consuming than simple comparision of unique int values.

You can do it with boost.MPL.

I would go simple route:
For classes that would be static property - so just pick a number for each class.
For instances - just use the address.

Static const's are evaluated at compile time - which is pretty much the basis for metaprogramming at large. Moreover, type_info::hash_code is particularly adapted for your needs, so try -
class MyClass
{
static const size_t TypeHashCode = typeid(MyClass).hash_code();
...
}
(I'm not around a compiler right now, so this may take some refining. Will try and recheck tomorrow)
EDIT: indeed, it is not only MS specific but also added only in VS2010 - but hey, at least MS agrees this is a valid need. If you don't allow both VS2010 and boost in your code - you're pretty much left with the standard compliant facilities: typeid or dynamic_cast. They do incur some overhead, but I'd take extra care to verify this overhead is indeed a worthy battle. (my money goes to - not.)

All such classes share something common. Then why not add a symbolic constant in a common enum for each one, you'll leave the enum give values for you, it's easier than giving explicit constants (you still have to declare each class in the enum).

template<class T>
struct provide_hash_code_for_class
{
public:
static uintptr_t GetHashCode()
{
return(reinterpret_cast<uintptr_t>(&unused));
}
private:
static void *unused;
};
template<class T>
void *provide_hash_code_for_class<T>::unused;
class MyClass : public provide_hash_code_for_class<MyClass>
{
};
int main()
{
std::cout << std::hex << MyClass::GetHashCode() << std::endl;
std::cout << std::hex << MyClass().GetHashCode() << std::endl;
return(0);
}
Please be aware that hash codes will change between runs so you can't rely on them for example for interprocess communication.

building on the simple route route by Nikolai N Fetissov:
For classes that would be static property - use the address of a function cast to an intptr_t to give a unique yet compiled-in value.
For instances - just use the address.

It is a pitty that there is no compile-time type hash_code supported by the standard. As a workaround, one can generate a compile time hash from the class name. An example below.
#include <stdint.h>
#include <string>
#include <vector>
#include <iostream>
#include <memory>
#include <cassert>
//Compile-time string hashing.
class HashedString
{
public:
typedef int64_t HashType;
explicit constexpr HashedString(const char* str): m_hash(hashString(str)) {}
static inline constexpr HashType hashString(const char* str)
{
return ( !str ? 0 : hashStringRecursive(5381, str));
}
static inline constexpr HashType hashStringRecursive(HashType hash, const char* str)
{
return ( !*str ? hash : hashStringRecursive(((hash << 5) + hash) + *str, str + 1));
}
const HashType m_hash;
};
struct EventBase
{
using IdType = HashedString::HashType;
virtual ~EventBase() {}
IdType getId() const { return m_eventId; } //present the runtime event id
EventBase(IdType myId) : m_eventId { myId } { }
template<class DerivedEvent>
const DerivedEvent* getAs() const
{
return dynamic_cast<const DerivedEvent*>(this);
}
protected:
const IdType m_eventId;
};
#define DEFINE_EVENT_ID(className) \
static constexpr IdType id = HashedString(#className).m_hash; \
struct SomeEvent1 : public EventBase
{
DEFINE_EVENT_ID(SomeEvent1);
SomeEvent1(int status) : EventBase(id), m_status { status } { assert(id == m_eventId); }
int m_status;
};
struct SomeEvent2 : public EventBase
{
DEFINE_EVENT_ID(SomeEvent2);
SomeEvent2() : EventBase(id) { assert(id == m_eventId); }
std::string m_s = "test event 2";
};
void testEvents()
{
std::vector<std::shared_ptr<EventBase>> events;
events.push_back(std::make_shared<SomeEvent1>(123));
events.push_back(std::make_shared<SomeEvent2>());
for (auto event : events) {
switch(event->getId()) {
case SomeEvent1::id:
std::cout << "SomeEvent1 " << event->getAs<SomeEvent1>()->m_status << std::endl;
break;
case SomeEvent2::id:
std::cout << "SomeEvent2 " << event->getAs<SomeEvent2>()->m_s << std::endl;
break;
}
}
}

Related

Can static polymorphism (templates) be used despite type erasure?

Having returned relatively recently to C++ after decades of Java, I am currently struggling with a template-based approach to data conversion for instances where type erasure has been applied. Please bear with me, my nomenclature may still be off for C++-natives.
This is what I am trying to achieve:
Implement dynamic variables which are able to hold essentially any value type
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to hold variable instances in containers, independent of their value type
Convert between variable value and representation using conversion functions
Be able to introduce new representations just by providing new conversion functions
Constraints: use only C++-11 features if possible, no use of libraries like boost::any etc.
A rough sketch of this might look like this:
#include <iostream>
#include <vector>
void convert(const std::string &f, std::string &t) { t = f; }
void convert(const int &f, std::string &t) { t = std::to_string(f); }
void convert(const std::string &f, int &t) { t = std::stoi(f); }
void convert(const int &f, int &t) { t = f; }
struct Variable {
virtual void get(int &i) = 0;
virtual void get(std::string &s) = 0;
};
template <typename T> struct VariableImpl : Variable {
T value;
VariableImpl(const T &v) : value{v} {};
void get(int &i) { convert(value, i); };
void get(std::string &s) { convert(value, s); };
};
int main() {
VariableImpl<int> v1{42};
VariableImpl<std::string> v2{"1234"};
std::vector<Variable *> vars{&v1, &v2};
for (auto &v : vars) {
int i;
v->get(i);
std::string s;
v->get(s);
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
return 0;
}
The code does what it is supposed to do, but obvoiusly I would like to get rid of Variable::get(int/std::string/...) and instead template them, because otherwise every new representation requires a definition and an implementation with the latter being exactly the same as all the others.
I've played with various approaches so far, like virtual templated, methods, applying the CRDT with intermediate type, various forms of wrappers, yet in all of them I get bitten by the erased value type of VariableImpl. On one hand, I think there might not be a solution, because after type erasure, the compiler cannot possibly know what templated getters and converter calls it must generate. On the other hand I think i might be missing something really essential here and there should be a solution despite the constraints mentioned above.
This is a classical double dispatch problem. The usual solution to this problem is to have some kind of dispatcher class with multiple implementations of the function you want to dispatch (get in your case). This is called the visitor pattern. The well-known drawback of it is the dependency cycle it creates (each class in the hierarchy depends on all other classes in the hierarchy). Thus there's a need to revisit it each time a new type is added. No amount of template wizardry eliminates it.
You don't have a specialised Visitor class, your Variable serves as a Visitor of itself, but this is a minor detail.
Since you don't like this solution, there is another one. It uses a registry of functions populated at run time and keyed on type identification of their arguments. This is sometimes called "Acyclic Visitor".
Here's a half-baked C++11-friendly implementation for your case.
#include <map>
#include <vector>
#include <typeinfo>
#include <typeindex>
#include <utility>
#include <functional>
#include <string>
#include <stdexcept>
struct Variable
{
virtual void convertValue(Variable& to) const = 0;
virtual ~Variable() {};
virtual std::type_index getTypeIdx() const = 0;
template <typename K> K get() const;
static std::map<std::pair<std::type_index, std::type_index>,
std::function<void(const Variable&, Variable&)>>
conversionMap;
template <typename T, typename K>
static void registerConversion(K (*fn)(const T&));
};
template <typename T>
struct VariableImpl : Variable
{
T value;
VariableImpl(const T &v) : value{v} {};
VariableImpl() : value{} {}; // this is needed for a declaration of
// `VariableImpl<K> below
// It can be avoided but it is
// a story for another day
void convertValue(Variable& to) const override
{
auto typeIdxFrom = getTypeIdx();
auto typeIdxTo = to.getTypeIdx();
if (typeIdxFrom == typeIdxTo) // no conversion needed
{
dynamic_cast<VariableImpl<T>&>(to).value = value;
}
else
{
auto fcnIter = conversionMap.find({getTypeIdx(), to.getTypeIdx()});
if (fcnIter != conversionMap.end())
{
fcnIter->second(*this, to);
}
else
throw std::logic_error("no conversion");
}
}
std::type_index getTypeIdx() const override
{
return std::type_index(typeid(T));
}
};
template <typename K> K Variable::get() const
{
VariableImpl<K> vk;
convertValue(vk);
return vk.value;
}
template <typename T, typename K>
void Variable::registerConversion(K (*fn)(const T&))
{
// add a mutex if you ever spread this over multiple threads
conversionMap[{std::type_index(typeid(T)), std::type_index(typeid(K))}] =
[fn](const Variable& from, Variable& to) {
dynamic_cast<VariableImpl<K>&>(to).value =
fn(dynamic_cast<const VariableImpl<T>&>(from).value);
};
}
Now of course you need to call registerConversion e.g. at the beginning of main and pass it each conversion function.
Variable::registerConversion(int_to_string);
Variable::registerConversion(string_to_int);
This is not ideal, but hardly anything is ever ideal.
Having said all that, I would recommend you revisit your design. Do you really need all these conversions? Why not pick one representation and stick with it?
Implement dynamic variables which are able to hold essentially any value type
Be able to hold variable instances in containers, independent of their value type
These two requirements are quite challenging on its own. The class templates don't really encourage inheritance, and you already did the right thing to hold what you asked for: introduced a common base class for the class template, which you can later refer to in order to store pointers of the said type in a collection.
Access the content of those variables using various other representations (string, ints, binary, ...)
Be able to introduce new representations just by providing new conversion functions
This is where it breaks. Function templates assume common implementation for different types, while inheritance assumes different implementation for the same types.
You goal is to introduce different implementation for different types, and in order to make your requirements viable you have to switch to one of those two options instead (or put up with a number of functions for each case which you have already introduced yourself)
Edit:
One of the strategies you may employ to enforce inheritance approach is generalisation of the arguments to the extent where they can be used interchangeably by the abstract interface. E.g. you may wrap the converting arguments inside of a union like this:
struct Variable {
struct converter_type {
enum { INT, STRING } type;
union {
int* m_int;
std::string* m_string;
};
};
virtual void get(converter_type& var) = 0;
virtual ~Variable() = default;
};
And then take whatever part of it inside of the implementation:
void get(converter_type& var) override {
switch (var.type) {
case converter_type::INT:
convert(value, var.m_int);
break;
case converter_type::STRING:
convert(value, var.m_string);
break;
}
}
To be honest I don't think this is a less verbose approach compared to just having a number of functions for each type combination, but i think you got the idea that you can just wrap your arguments somehow to cement the abstract class interface.
Implement std::any. It is similar to boost::any.
Create a conversion dispatcher based off typeids. Store your any alongside the conversion dispatcher.
"new conversion functions" have to be passed to the dispatcher.
When asked to convert to a type, pass that typeid to the dispatcher.
So we start with these 3 types:
using any = std::any; // implement this
using converter = std::function<any(any const&)>;
using convert_table = std::map<std::type_index, converter>;
using convert_lookup = convert_table(*)();
template<class T>
convert_table& lookup_convert_table() {
static convert_table t;
return t;
}
struct converter_any: any {
template<class T,
typename std::enable_if<
!std::is_same<typename std::decay<T>::type, converter_any>::value, bool
>::type = true
>
converter_any( T&& t ):
any(std::forward<T>(t)),
table(&lookup_convert_table<typename std::decay<T>::type>())
{}
converter_any(converter_any const&)=default;
converter_any(converter_any &&)=default;
converter_any& operator=(converter_any const&)=default;
converter_any& operator=(converter_any&&)=default;
~converter_any()=default;
converter_any()=default;
convert_table const* table = nullptr;
template<class U>
U convert_to() const {
if (!table)
throw 1; // make a better exception than int
auto it = table->find(typeid(U));
if (it == table->end())
throw 2; // make a better exception than int
any const& self = *this;
return any_cast<U>((it->second)(self));
}
};
template<class Dest, class Src>
bool add_converter_to_table( Dest(*f)(Src const&) ) {
lookup_convert_table<Src>()[typeid(Dest)] = [f](any const& s)->any {
Src src = std::any_cast<Src>(s);
auto r = f(src);
return r;
};
return true;
}
now your code looks like:
const bool bStringRegistered =
add_converter_to_table(+[](std::string const& f)->std::string{ return f; })
&& add_converter_to_table(+[](std::string const& f)->int{ return std::stoi(f); });
const bool bIntRegistered =
add_converter_to_table(+[](int const& i)->int{ return i; })
&& add_converter_to_table(+[](int const& i)->std::string{ return std::to_string(i); });
int main() {
converter_any v1{42};
converter_any v2{std::string("1234")};
std::vector<converter_any> vars{v1, v2}; // copies!
for (auto &v : vars) {
int i = v.convert_to<int>();
std::string s = v.convert_to<std::string>();
std::cout << "int representation: " << i <<
", string representation: " << s << std::endl;
}
}
live example.
...
Ok, what did I do?
I used any to be a smart void* that can store anything. Rewriting this is a bad idea, use someone else's implementation.
Then, I augmented it with a manually written virtual function table. Which table I add is determined by the constructor of my converter_any; here, I know the type stored, so I can store the right table.
Typically when using this technique, I'd know what functions are in there. For your implementation we do not; so the table is a map from the type id of the destination, to a conversion function.
The conversion function takes anys and returns anys -- again, don't repeat this work. And now it has a fixed signature.
To add support for a type, you independently register conversion functions. Here, my conversion function registration helper deduces the from type (to determine which table to register it in) and the destination type (to determine which entry in the table), and then automatically writes the any boxing/unboxing code for you.
...
At a higher level, what I'm doing is writing my own type erasure and object model. C++ has enough power that you can write your own object models, and when you want features that the default object model doesn't solve, well, roll a new object model.
Second, I'm using value types. A Java programmer isn't used to value types having polymorphic behavior, but much of C++ works much better if you write your code using value types.
So my converter_any is a polymorphic value type. You can store copies of them in vectors etc, and it just works.

Cast structs with certain common members

Lets say I have 2 structs:
typedef struct
{
uint8_t useThis;
uint8_t u8Byte2;
uint8_t u8Byte3;
uint8_t u8Byte4;
} tstr1
and
typedef struct
{
uint8_t u8Byte1;
uint8_t u8Byte2;
uint8_t useThis;
} tstr2
I will only need the useThis member inside a function, but in some cases I will need to cast one struct or the other:
void someFunction()
{
someStuff();
SOMETHING MyInstance;
if(someVariable)
{
MyInstance = reinterpret_cast<tstr1*>(INFO_FROM_HARDWARE); //This line of course doesn't work
}
else
{
MyInstance = reinterpret_cast<tstr2*>(INFO_FROM_HARDWARE); //This line of course doesn't work
}
MyInstance->useThis; //Calling this memeber with no problem
moreStuff();
}
So I want to use useThis no matter what cast was done. How can this be done?
I want to avoid someFunction() to be template (just to avoid this kind of things)
Note tha questions like this have a kind of similar problem but the struct members have the same order
EDIT:
In RealLife these structs are way larger and have several "same named" members. Directly casting a uint8_t as reinterpret_cast<tstr1*>(INFO_FROM_HARDWARE)->useThis would be tedious and require several reinterpret_casts (althought it's a working solution for my question before this EDIT). This is why I insist on MyInstance being "complete".
This is what templates are for:
template<class tstr>
std::uint8_t
do_something(std::uint8_t* INFO_FROM_HARDWARE)
{
tstr MyInstance;
std::memcpy(&MyInstance, INFO_FROM_HARDWARE, sizeof MyInstance);
MyInstance.useThis; //Calling this memeber with no problem
// access MyInstance within the template
}
// usage
if(someVariable)
{
do_something<tstr1>(INFO_FROM_HARDWARE);
}
else
{
do_something<tstr2>(INFO_FROM_HARDWARE);
}
I want to avoid someFunction() to be template (just to avoid this kind of things)
Why can’t I separate the definition of my templates class from its declaration and put it inside a .cpp file?
The linked problem isn't an issue for your use case because the potential set of template arguments is a finite set. The very next FAQ entry explains how: Use explicit instantiations of the template.
as suggested by AndyG, how about std::variant (there's no mention of the c++ standard you are using so maybe a c++17 solution is ok - also worth using <insert other variant implementation> if no c++17 available).
here's an example
std::variant knows what type is stored in it and you can use visit anytime you wish to use any of the members in there (snippet here for clarity):
// stolen from #eerrorika (sorry for that :( )
struct hardware {
uint8_t a = 'A';
uint8_t b = 'B';
uint8_t c = 'C';
uint8_t d = 'D';
};
struct tstr1 {
uint8_t useThis;
uint8_t u8Byte2;
uint8_t u8Byte3;
uint8_t u8Byte4;
};
struct tstr2 {
uint8_t u8Byte1;
uint8_t u8Byte2;
uint8_t useThis;
};
// stuff
if(true)
{
msg = *reinterpret_cast<tstr1*>(&hw);
}
else
{
msg = *reinterpret_cast<tstr2*>(&hw);
}
std::visit(overloaded {
[](tstr1 const& arg) { std::cout << arg.useThis << ' '; },
[](tstr2 const& arg) { std::cout << arg.useThis << ' '; }
}, msg);
EDIT: you can also do a variant of pointers
EDIT2: forgot to escape some stuff...
Using virtual dispatch is usually not what you want when mapping to hardware but it is an alternative.
Example:
// define a common interface
struct overlay_base {
virtual ~overlay_base() = default;
virtual uint8_t& useThis() = 0;
virtual uint8_t& useThat() = 0;
};
template<class T>
class wrapper : public overlay_base {
public:
template<class HW>
wrapper(HW* hw) : instance_ptr(reinterpret_cast<T*>(hw)) {}
uint8_t& useThis() { return instance_ptr->useThis; }
uint8_t& useThat() { return instance_ptr->useThat; }
private:
T* instance_ptr;
};
With that, you can declare a base class pointer, assign it, and use after the if statement:
int main(int argc, char**) {
std::unique_ptr<overlay_base> MyInstance;
if(argc % 2) {
MyInstance.reset( new wrapper<tstr1>(INFO_FROM_HARDWARE) );
} else {
MyInstance.reset( new wrapper<tstr2>(INFO_FROM_HARDWARE) );
}
std::cout << MyInstance->useThis() << '\n';
std::cout << MyInstance->useThat() << '\n';
}
Demo
Explanation regarding my comment: "It works, but unless the compiler is really clever and can optimize away the virtual dispatch in your inner loops, it's going to be slower than if you actually take the time to type cast":
Think of virtual dispatch as having a lookup table (vtable) used at runtime (which is often what actually happens). When calling a virtual function, the program has to use that lookup table to find the address of the actual member function to call. When it's impossible to optimize away the lookup (as I made sure in my example above by using a value only available at runtime) it does take a few CPU cycles extra compared to what you'd get by doing a static cast.
A simple reference to the struct member might be what you need:
uint8_t &useThis=SomeVariable
?reinterpret_cast<tstr1*>(INFO_FROM_HARDWARE)->useThis
:reinterpret_cast<tstr2*>(INFO_FROM_HARDWARE)->useThis;

C++11 indexing template parameter packs at runtime in order to access Nth type

From this SO topic (and this blog post), I know how to access Nth type in a template parameter pack. For instance, one of the answers to the abovementioned SO question suggests this:
template<int N, typename... Ts> using NthTypeOf = typename std::tuple_element<N, std::tuple<Ts...>>::type;
using ThirdType = NthTypeOf<2, Ts...>;
However, these methods work only in compile-time. Trying to do something such as:
int argumentNumber = 2;
using ItsType = NthTypeOf<argumentNumber, Arguments...>;
would result in compile error:
Error : non-type template argument is not a constant expression
Is there a way to access Nth type at runtime?
Here's my use case:
My program reads a text file, which is basically an array of numbers. Each number i refers to the i-th type of a template parameter pack that my class is templated based on. Based on that type, I want to declare a variable of that type and do something differently with it. For example, if it's a string, I want to declare a string and do string matching, and if it's an integer, I would like to compute the square root of a number.
C++ is a statically​ typed language. As such the type of all variables needs to be known at compile time (and cannot vary). You want a type that depends on a runtime value. Luckily C++ also features dynamic typing of objects.
Warning: all code in this answer serves only for demonstration of the basic concept/idea. It's missing any kind of error handling, sane interfaces (constructors...), exception safety, ... . So don't use for production, consider using the implementations​ available from boost.
To use this feature you need what's called a polymorphic base class: a class with (at least) one virtual member function from which you derive further classes.
struct value_base {
// you want to be able to make copies
virtual std::unique_ptr<value_base> copy_me() const = 0;
virtual ~value_base () {}
};
template<typename Value_Type>
struct value_of : value_base {
Value_Type value;
std::unique_ptr<value_base> copy_me() const {
return new value_of {value};
}
};
You can then have a variable with static type of pointer or reference to that base class, which can point to/reference objects from both the base class as well as from any of those derived classes. If you have a clearly defined interface, then encode that as virtual member functions (think of Shape and area (), name (), ... functions) and make calls through that base class pointer/reference (as shown in the other answer). Otherwise use a (hidden) dynamic cast to obtain a pointer/reference with static type of the dynamic type:
struct any {
std:: unique_ptr<value_base> value_container;
// Add constructor
any(any const & a)
: value_container (a.value_container->copy_me ())
{}
// Move constructor
template<typename T>
T & get() {
value_of<T> * typed_container
= dynamic_cast<value_of<T> *>(value_container.get();)
if (typed_container == nullptr) {
// Stores another type, handle failure
}
return typed_container->value;
}
// T const & get() const;
// with same content as above
};
template<typename T, typename... Args>
any make_any (Args... && args) {
// Raw new, not good, add proper exception handling like make_unique (C++14?)
return {new T(std:: forward<Args>(args)...)};
}
Since object construction is done at runtime the actual type of the pointed to/referenced object may depend on runtime values:
template<typename T>
any read_and_construct (std:: istream & in) {
T value;
// Add error handling please
in >> value;
return make_any<T>(std:: move (value));
}
// ...
// missing: way of error handling
std::map<int, std:: function<any(std:: istream &)>> construction_map;
construction_map.insert(std::make_pair(1, read_and_construct<double>));
// and more
int integer_encoded_type;
// error handling please
cin >> integer_encoded_type;
// error handling please
any value = construction_map [integer_encoded_type] (cin);
As you may have noticed above code uses also a clearly defined interface for construction. If you don't intend to do lots of different things with the returned any objects, potentially storing them in various data structures over great parts of the time your program is running, then using an any type is most likely overkill and you should just put the type dependent code into those construction functions, too.
A serious drawback of such an any class is its generality: it's possible to store just about any type within it. This means that the (maximum) size of the (actually) stored object is not known during compilation, making use of storage with automatic duration (the "stack") impossible (in standard C++). This may lead to expensive usage of dynamic memory (the "heap"), which is considerably slower than automatic memory. This issue will surface whenever many copies of any objects have to be made, but is probably irrelevant (except for cache locality) if you just keep a collection of them around.
Thus, if you know at compile time the set of types which you must be able to store, then you can (at compile time) compute the maximum size needed, use a static array of that size and construct your objects inside that array (since C++11 you can achieve the same with a (recursive template) union, too):
constexpr size_t max_two (size_t a, size_t b) {
return (a > b) ? a : b;
}
template<size_t size, size_t... sizes>
constexpr size_t max_of() {
return max_two (size, max_of<sizes>());
}
template<typename... Types>
struct variant {
alignas(value_of<Types>...) char buffer[max_of<sizeof (value_of<Types>)...>()];
value_base * active;
// Construct an empty variant
variant () : active (nullptr)
{}
// Copy and move constructor still missing!
~variant() {
if (active) {
active->~value_base ();
}
}
template<typename T, typename... Args>
void emplace (Args... && args) {
if (active) {
active->~value_base ();
}
active = new (buffer) T(std:: forward<Args>(args)...);
}
};
C++ is a statically-typed language, which means that the types of variables cannot be decided or changed at runtime.
Because your array of numbers are input at runtime, it's impossible for you to use the NthTypeOf metafunction in the manner you describe, because NthTypeOf can only depend on a compile-time index.
In your use case, not only are the variables of different type, but the behavior is also different based on user input.
If you want different behavior based on a value determined at runtime, I suggest either a switch statement, a container of std::function, or a heterogeneous container of polymorphic "command" objects.
A solution based on a switch statement is pretty trivial, so I won't bother showing an example.
A std::function is a polymorphic wrapper around a function-like object. You can use a container of std::function to build a sort of dispatch table.
struct StringMatch
{
void operator()() const
{
std::string s1, s2;
std::cin >> s1 >> s2;
if (s1 == s2)
std::cout << "Strings match\n";
else
std::cout << "Strings don't match\n";
}
};
struct SquareRoot
{
void operator()() const
{
float x = 0;
std::cin >> x;
std::cout << "Square root is " << std::sqrt(x) <<"\n";
}
};
int main()
{
const std::map<int, std::function> commands =
{
{1, StringMatch()},
{2, SquareRoot()},
};
int commandId = 0;
std::cin >> commandId;
auto found = command.find(commandId);
if (found != commands.end())
(*found->second)();
else
std::cout << "Unknown command";
return 0;
}
The map can of course be replaced by a flat array or vector, but then you need to worry about "holes" in the command ID range.
If you need your command objects to be able to do more then execute themselves (like having properties, or support undo/redo), you can use a solution that uses polymorphism and is inspired by the traditional Command Pattern.
class Command
{
public:
virtual ~Command() {}
virtual void execute();
virtual std::string name() const;
virtual std::string description() const;
};
class StringMatch : public Command
{
public:
void execute() override
{
std::string s1, s2;
std::cin >> s1 >> s2;
if (s1 == s2)
std::cout << "Strings match\n";
else
std::cout << "Strings don't match\n";
}
std::string name() const override {return "StringMatch";}
std::string description() const override {return "Matches strings";}
};
class SquareRoot : public Command
{
public:
void execute() override
{
float x = 0;
std::cin >> x;
std::cout << "Square root is " << std::sqrt(x) <<"\n";
}
std::string name() const override {return "SquareRoot";}
std::string description() const override {return "Computes square root";}
};
int main()
{
constexpr int helpCommandId = 0;
const std::map<int, std::shared_ptr<Command>> commands =
{
{1, std::make_shared<StringMatch>()},
{2, std::make_shared<SquareRoot>()},
};
int commandId = 0;
std::cin >> commandId;
if (commandId == helpCommandId)
{
// Display command properties
for (const auto& kv : commands)
{
int id = kv.first;
const Command& cmd = *kv.second;
std::cout << id << ") " << cmd.name() << ": " << cmd.description()
<< "\n";
}
}
else
{
auto found = command.find(commandId);
if (found != commands.end())
found->second->execute();
else
std::cout << "Unknown command";
}
return 0;
}
Despite C++ being a statically-typed language, there are ways to emulate Javascript-style dynamic variables, such as the JSON for Modern C++ library or Boost.Variant.
Boost.Any can also be used for type erasure of your command arguments, and your command objects/functions would know how to downcast them back to their static types.
But such emulated dynamic variables will not address your need to have different behavior based on user/file input.
One possible approach when you want to do something with a run-time dependent type very locally, is to predict run-time values at the compile time.
using Tuple = std::tuple<int, double, char>;
int type;
std::cin >> type;
switch(type) {
case 0: {
using ItsType = std::tuple_element<0, Tuple>;
break;
}
case 1: {
using ItsType = std::tuple_element<1, Tuple>;
break;
}
default: std::cerr << "char is not handled yet." << std::endl;
break;
}
Only works with small type packs, of course.
Is there a way to access Nth type at runtime?
Yes, although per other answers, it may not be appropriate in this context.
Adapting this answer, you can iterate at compile time, and choose a type.
#include <iostream>
#include <fstream>
#include <string>
#include <type_traits>
#include <tuple>
#include <cmath>
std::ifstream in("my.txt");
void do_something(const std::string& x)
{
std::cout << "Match " << x << '\n';
}
void do_something(int x)
{
std::cout << "Sqrt of " << x << " = " << std::sqrt(x) << '\n';
}
template<std::size_t I, typename... Tp>
inline typename std::enable_if_t<I == sizeof...(Tp)> action_on_index_impl(size_t)
{ // reached end with I==number of types: do nothing
}
template<std::size_t I, typename... Tp>
inline typename std::enable_if_t<I < sizeof...(Tp)> action_on_index_impl(size_t i)
{
if (i == I){
// thanks to https://stackoverflow.com/a/29729001/834521 for following
std::tuple_element_t<I, std::tuple<Tp...>> x{};
in >> x;
do_something(x);
}
else
action_on_index_impl<I+1, Tp...>(i);
}
template<typename... Tp> void action_on_index(size_t i)
{
// start at the beginning with I=0
action_on_index_impl<0, Tp...>(i);
}
int main()
{
int i{};
while(in >> i, in)
action_on_index<std::string, int>(i);
return 0;
}
with my.txt
0 hello
1 9
0 world
1 4
output
Match hello
Sqrt of 9 = 3
Match world
Sqrt of 4 = 2
I needed to know how to access Nth type at runtime in a different context, hence my answer here (I wonder if there is a better way, particularly in C++14/17).

C++: can you force the access to a private member of a class? [duplicate]

Disclaimer
Yes, I am fully aware that what I am asking about is totally stupid and that anyone who would wish to try such a thing in production code should be fired and/or shot. I'm mainly looking to see if can be done.
Now that that's out of the way, is there any way to access private class members in C++ from outside the class? For example, is there any way to do this with pointer offsets?
(Naive and otherwise non-production-ready techniques welcome)
Update
As noted in the comments, I asked this question because I wanted to write a blog post on over-encapsulation (and how it affects TDD). I wanted to see if there was a way to say "using private variables isn't a 100% reliable way to enforce encapsulation, even in C++." At the end, I decided to focus more on how to solve the problem rather than why it's a problem, so I didn't feature some of the stuff brought up here as prominently as I had planned, but I still left a link.
At any rate, if anyone's interested in how it came out, here it is: Enemies of Test Driven Development part I: encapsulation (I suggest reading it before you decide that I'm crazy).
If the class contains any template member functions you can specialize that member function to suit your needs. Even if the original developer didn't think of it.
safe.h
class safe
{
int money;
public:
safe()
: money(1000000)
{
}
template <typename T>
void backdoor()
{
// Do some stuff.
}
};
main.cpp:
#include <safe.h>
#include <iostream>
class key;
template <>
void safe::backdoor<key>()
{
// My specialization.
money -= 100000;
std::cout << money << "\n";
}
int main()
{
safe s;
s.backdoor<key>();
s.backdoor<key>();
}
Output:
900000
800000
I've added an entry to my blog (see below) that shows how it can be done. Here is an example on how you use it for the following class
struct A {
private:
int member;
};
Just declare a struct for it where you describe it and instantiate the implementation class used for robbery
// tag used to access A::member
struct A_member {
typedef int A::*type;
friend type get(A_member);
};
template struct Rob<A_member, &A::member>;
int main() {
A a;
a.*get(A_member()) = 42; // write 42 to it
std::cout << "proof: " << a.*get(A_member()) << std::endl;
}
The Rob class template is defined like this, and needs only be defined once, regardless how many private members you plan to access
template<typename Tag, typename Tag::type M>
struct Rob {
friend typename Tag::type get(Tag) {
return M;
}
};
However, this doesn't show that c++'s access rules aren't reliable. The language rules are designed to protect against accidental mistakes - if you try to rob data of an object, the language by-design does not take long ways to prevent you.
The following is sneaky, illegal, compiler-dependent, and may not work depending on various implementation details.
#define private public
#define class struct
But it is an answer to your OP, in which you explicitly invite a technique which, and I quote, is "totally stupid and that anyone who would wish to try such a thing in production code should be fired and/or shot".
Another technique is to access private member data, by contructing pointers using hard-coded/hand-coded offsets from the beginning of the object.
Hmmm, don't know if this would work, but might be worth a try. Create another class with the same layout as the object with private members but with private changed to public. Create a variable of pointer to this class. Use a simple cast to point this to your object with private members and try calling a private function.
Expect sparks and maybe a crash ;)
class A
{
int a;
}
class B
{
public:
int b;
}
union
{
A a;
B b;
};
That should do it.
ETA: It will work for this sort of trivial class, but as a general thing it won't.
TC++PL Section C.8.3: "A class with a constructor, destructor, or copy operation cannot be the type of a union member ... because the compiler would not know which member to destroy."
So we're left with the best bet being to declare class B to match A's layout and hack to look at a class's privates.
If you can get a pointer to a member of a class you can use the pointer no matter what the access specifiers are (even methods).
class X;
typedef void (X::*METHOD)(int);
class X
{
private:
void test(int) {}
public:
METHOD getMethod() { return &X::test;}
};
int main()
{
X x;
METHOD m = x.getMethod();
X y;
(y.*m)(5);
}
Of course my favorite little hack is the friend template back door.
class Z
{
public:
template<typename X>
void backDoor(X const& p);
private:
int x;
int y;
};
Assuming the creator of the above has defined backDoor for his normal uses. But you want to access the object and look at the private member variables. Even if the above class has been compiled into a static library you can add your own template specialization for backDoor and thus access the members.
namespace
{
// Make this inside an anonymous namespace so
// that it does not clash with any real types.
class Y{};
}
// Now do a template specialization for the method.
template<>
void Z::backDoor<Y>(Y const& p)
{
// I now have access to the private members of Z
}
int main()
{
Z z; // Your object Z
// Use the Y object to carry the payload into the method.
z.backDoor(Y());
}
It's definately possible to access private members with a pointer offset in C++. Lets assume i had the following type definition that I wanted access to.
class Bar {
SomeOtherType _m1;
int _m2;
};
Assuming there are no virtual methods in Bar, The easy case is _m1. Members in C++ are stored as offsets of the memory location of the object. The first object is at offset 0, the second object at offset of sizeof(first member), etc ...
So here is a way to access _m1.
SomeOtherType& GetM1(Bar* pBar) {
return*(reinterpret_cast<SomeOtherType*>(pBar));
}
Now _m2 is a bit more difficult. We need to move the original pointer sizeof(SomeOtherType) bytes from the original. The cast to char is to ensure that I am incrementing in a byte offset
int& GetM2(Bar* pBar) {
char* p = reinterpret_cast<char*>(pBar);
p += sizeof(SomeOtherType);
return *(reinterpret_cast<int*>(p));
}
This answer is based on the exact concept demonstrated by #Johannes's answer/blog, as that seems to be the only "legitimate" way. I have converted that example code into a handy utility. It's easily compatible with C++03 (by implementing std::remove_reference & replacing nullptr).
Library
#define CONCATE_(X, Y) X##Y
#define CONCATE(X, Y) CONCATE_(X, Y)
#define ALLOW_ACCESS(CLASS, MEMBER, ...) \
template<typename Only, __VA_ARGS__ CLASS::*Member> \
struct CONCATE(MEMBER, __LINE__) { friend __VA_ARGS__ CLASS::*Access(Only*) { return Member; } }; \
template<typename> struct Only_##MEMBER; \
template<> struct Only_##MEMBER<CLASS> { friend __VA_ARGS__ CLASS::*Access(Only_##MEMBER<CLASS>*); }; \
template struct CONCATE(MEMBER, __LINE__)<Only_##MEMBER<CLASS>, &CLASS::MEMBER>
#define ACCESS(OBJECT, MEMBER) \
(OBJECT).*Access((Only_##MEMBER<std::remove_reference<decltype(OBJECT)>::type>*)nullptr)
API
ALLOW_ACCESS(<class>, <member>, <type>);
Usage
ACCESS(<object>, <member>) = <value>; // 1
auto& ref = ACCESS(<object>, <member>); // 2
Demo
struct X {
int get_member () const { return member; };
private:
int member = 0;
};
ALLOW_ACCESS(X, member, int);
int main() {
X x;
ACCESS(x, member) = 42;
std::cout << "proof: " << x.get_member() << std::endl;
}
If you know how your C++ compiler mangles names, yes.
Unless, I suppose, it's a virtual function. But then, if you know how your C++ compiler builds the VTABLE ...
Edit: looking at the other responses, I realize that I misread the question and thought it was about member functions, not member data. However, the point still stands: if you know how your compiler lays out data, then you can access that data.
cool question btw... here's my piece:
using namespace std;
class Test
{
private:
int accessInt;
string accessString;
public:
Test(int accessInt,string accessString)
{
Test::accessInt=accessInt;
Test::accessString=accessString;
}
};
int main(int argnum,char **args)
{
int x;
string xyz;
Test obj(1,"Shit... This works!");
x=((int *)(&obj))[0];
xyz=((string *)(&obj))[1];
cout<<x<<endl<<xyz<<endl;
return 0;
}
Hope this helps.
As an alternative to template backdoor method you can use template backdoor class. The difference is that you don't need to put this backdoor class into public area of the class your are going to test. I use the fact that many compilers allow nested classes to access private area of enclosing class (which is not exactly 1998 standard but considered to be "right" behaviour). And of course in C++11 this became legal behaviour.
See this example:
#include <vector>
#include <cassert>
#include <iostream>
using std::cout;
using std::endl;
///////// SystemUnderTest.hpp
class SystemUnderTest
{
//...put this 'Tested' declaration into private area of a class that you are going to test
template<typename T> class Tested;
public:
SystemUnderTest(int a): a_(a) {}
private:
friend std::ostream& operator<<(std::ostream& os, const SystemUnderTest& sut)
{
return os << sut.a_;
}
int a_;
};
/////////TestFramework.hpp
class BaseTest
{
public:
virtual void run() = 0;
const char* name() const { return name_; }
protected:
BaseTest(const char* name): name_(name) {}
virtual ~BaseTest() {}
private:
BaseTest(const BaseTest&);
BaseTest& operator=(const BaseTest&);
const char* name_;
};
class TestSuite
{
typedef std::vector<BaseTest*> Tests;
typedef Tests::iterator TIter;
public:
static TestSuite& instance()
{
static TestSuite TestSuite;
return TestSuite;
}
void run()
{
for(TIter iter = tests_.begin(); tests_.end() != iter; ++iter)
{
BaseTest* test = *iter;
cout << "Run test: " << test->name() << endl;
test->run();
}
}
void addTest(BaseTest* test)
{
assert(test);
cout << "Add test: " << test->name() << endl;
tests_.push_back(test);
}
private:
std::vector<BaseTest*> tests_;
};
#define TEST_CASE(SYSTEM_UNDER_TEST, TEST_NAME) \
class TEST_NAME {}; \
template<> \
class SYSTEM_UNDER_TEST::Tested<TEST_NAME>: public BaseTest \
{ \
Tested(): BaseTest(#SYSTEM_UNDER_TEST "::" #TEST_NAME) \
{ \
TestSuite::instance().addTest(this); \
} \
void run(); \
static Tested instance_; \
}; \
SYSTEM_UNDER_TEST::Tested<TEST_NAME> SYSTEM_UNDER_TEST::Tested<TEST_NAME>::instance_; \
void SYSTEM_UNDER_TEST::Tested<TEST_NAME>::run()
//...TestSuiteForSystemUnderTest.hpp
TEST_CASE(SystemUnderTest, AccessPrivateValueTest)
{
SystemUnderTest sut(23);
cout << "Changed private data member from " << sut << " to ";
sut.a_ = 12;
cout << sut << endl;
}
//...TestRunner.cpp
int main()
{
TestSuite::instance().run();
}
Beside #define private public you can also #define private protected and then define some foo class as descendant of wanted class to have access to it's (now protected) methods via type casting.
just create your own access member function to extend the class.
To all the people suggesting "#define private public":
This kind of thing is illegal. The standard forbids defining/undef-ing macros that are lexically equivalent to reserved language keywords. While your compiler probably won't complain (I've yet to see a compiler that does), it isn't something that's a "Good Thing" to do.
It's actually quite easy:
class jail {
int inmate;
public:
int& escape() { return inmate; }
};
"using private variables isn't a 100% reliable way to enforce encapsulation, even in C++."
Really? You can disassemble the library you need, find all the offsets needed and use them.
That will give you an ability to change any private member you like... BUT!
You can't access private members without some dirty hacking.
Let us say that writing const won't make your constant be really constant, 'cause you can
cast const away or just use it's address to invalidate it. If you're using MSVC++ and you specified "-merge:.rdata=.data" to a linker, the trick will work without any memory access faults.
We can even say that writing apps in C++ is not reliable way to write programs, 'cause resulting low level code may be patched from somewhere outside when your app is running.
Then what is reliable documented way to enforce encapsulation? Can we hide the data somewhere in RAM and prevent anything from accessing them except our code? The only idea I have is to encrypt private members and backup them, 'cause something may corrupt those members.
Sorry if my answer is too rude, I didn't mean to offend anybody, but I really don't think that statement is wise.
since you have an object of required class I am guessing that you have declaration of class.
Now what you can do is declare another class with same members but keep all of there access specifiers as public.
For example previous class is:
class Iamcompprivate
{
private:
Type1 privateelement1;
Typ2 privateelement2;
...
public:
somefunctions
}
you can declare a class as
class NowIampublic
{
**public:**
Type1 privateelement1;
Type2 privateelement2;
...
somefunctions
};
Now all you need to do is cast pointer of class Iamcompprivate into an pointer of class NowIampublic and use them as U wish.
Example:
NowIampublic * changetopublic(Iamcompprivate *A)
{
NowIampublic * B = (NowIampublic *)A;
return B;
}
By referencing to *this you enable a backdoor to all private data within an object.
class DumbClass
{
private:
int my_private_int;
public:
DumbClass& backdoor()
{
return *this;
}
}
Quite often a class provides mutator methods to private data (getters and setters).
If a class does provide a getter that returns a const reference (but no setter), then you can just const_cast the return value of the getter, and use that as an l-value:
class A {
private:
double _money;
public:
A(money) :
_money(money)
{}
const double &getMoney() const
{
return _money;
}
};
A a(1000.0);
const_cast<double &>(a.getMoney()) = 2000.0;
I've used another useful approach (and solution) to access a c++ private/protected member.
The only condition is that you are able to inherit from the class you want to access.
Then all credit goes to reinterpret_cast<>().
A possible problem is that it won't work if you insert a virtual function, which will modify virtual table, and so, object size/alignment.
class QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QObject)
void dumpObjectInfo();
void dumpObjectTree();
...
protected:
QScopedPointer<QObjectData> d_ptr;
...
}
class QObjectWrapper : public QObject
{
public:
void dumpObjectInfo2();
void dumpObjectTree2();
};
Then you just need to use the class as follows:
QObject* origin;
QObjectWrapper * testAccesor = reinterpret_cast<QObjectWrapper *>(origin);
testAccesor->dumpObjectInfo2();
testAccesor->dumpObjectTree2();
My original problem was as follows: I needed a solution that won't imply recompiling QT libraries.
There are 2 methods in QObject, dumpObjectInfo() and dumpObjectTree(), that
just work if QT libs are compiled in debug mode, and they of course need access to d_ptr proteted member (among other internal structures).
What I did was to use the proposed solution to reimplement (with copy and paste) those methods in dumpObjectInfo2() and dumpObjectTree2() in my own class (QObjectWrapper) removing those debug preprocesor guards.
The following code accesses and modifies a private member of the class using a pointer to that class.
#include <iostream>
using namespace std;
class A
{
int private_var;
public:
A(){private_var = 0;}//initialized to zero.
void print(){cout<<private_var<<endl;}
};
int main()
{
A ob;
int *ptr = (int*)&ob; // the pointer to the class is typecast to a integer pointer.
(*ptr)++; //private variable now changed to 1.
ob.print();
return 0;
}
/*prints 1. subsequent members can also be accessed by incrementing the pointer (and
type casting if necessary).*/
study purpose only....
try this ....may be helpfull i guess.....
this program can access the private data just by knowing the values...
//GEEK MODE....;)
#include<iostream.h>
#include<conio.h>
class A
{
private :int iData,x;
public: void get() //enter the values
{cout<<"Enter iData : ";
cin>>iData;cout<<"Enter x : ";cin>>x;}
void put() //displaying values
{cout<<endl<<"sum = "<<iData+x;}
};
void hack(); //hacking function
void main()
{A obj;clrscr();
obj.get();obj.put();hack();obj.put();getch();
}
void hack() //hack begins
{int hck,*ptr=&hck;
cout<<endl<<"Enter value of private data (iData or x) : ";
cin>>hck; //enter the value assigned for iData or x
for(int i=0;i<5;i++)
{ptr++;
if(*ptr==hck)
{cout<<"Private data hacked...!!!\nChange the value : ";
cin>>*ptr;cout<<hck<<" Is chaged to : "<<*ptr;
return;}
}cout<<"Sorry value not found.....";
}
Inspired by #Johannes Schaub - litb, the following code may be a bit easier to digest.
struct A {
A(): member(10){}
private:
int get_member() { return member;}
int member;
};
typedef int (A::*A_fm_ptr)();
A_fm_ptr get_fm();
template< A_fm_ptr p>
struct Rob{
friend A_fm_ptr get_fm() {
return p;
}
};
template struct Rob< &A::get_member>;
int main() {
A a;
A_fm_ptr p = get_fm();
std::cout << (a.*p)() << std::endl;
}
Well, with pointer offsets, it's quite easy. The difficult part is finding the offset:
other.hpp
class Foo
{
public:
int pub = 35;
private:
int foo = 5;
const char * secret = "private :)";
};
main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include "other.hpp"
unsigned long long getPrivOffset(
const char * klass,
const char * priv,
const char * srcfile
){
std::ifstream read(srcfile);
std::ofstream write("fork.hpp");
std::regex r ("private:");
std::string line;
while(getline(read, line))
// make all of the members public
write << std::regex_replace(line, r, "public:") << '\n';
write.close();
read.close();
// find the offset, using the clone object
std::ofstream phony("phony.cpp");
phony <<
"#include <iostream>\n"
"#include <fstream>\n"
"#include \"fork.hpp\"\n"
"int main() {\n";
phony << klass << " obj;\n";
// subtract to find the offset, the write it to a file
phony <<
"std::ofstream out(\"out.txt\");\n out << (((unsigned char *) &(obj."
<< priv << ")) -((unsigned char *) &obj)) << '\\n';\nout.close();";
phony << "return 0;\n}";
phony.close();
system(
"clang++-7 -o phony phony.cpp\n"
"./phony\n"
"rm phony phony.cpp fork.hpp");
std::ifstream out("out.txt");
// read the file containing the offset
getline(out, line);
out.close();
system("rm out.txt");
unsigned long long offset = strtoull(line.c_str(), NULL, 10);
return offset;
}
template <typename OutputType, typename Object>
OutputType hack(
Object obj,
const char * objectname,
const char * priv_method_name,
const char * srcfile
) {
unsigned long long o = getPrivOffset(
objectname,
priv_method_name,
srcfile
);
return *(OutputType *)(((unsigned char *) (&obj)+o));
}
#define HACK($output, $object, $inst, $priv, $src)\
hack <$output, $object> (\
$inst,\
#$object,\
$priv,\
$src)
int main() {
Foo bar;
std::cout << HACK(
// output type
const char *,
// type of the object to be "hacked"
Foo,
// the object being hacked
bar,
// the desired private member name
"secret",
// the source file of the object's type's definition
"other.hpp"
) << '\n';
return 0;
}
clang++ -o main main.cpp
./main
output:
private :)
You could also use reinterpret_cast.
Maybe some pointer arithmetics can do it
#pragma pack(1)
class A
{
int x{0};
char c{0};
char s[8]{0};
public:
void display()
{
print(x);
print(c);
print(s);
};
};
int main(void)
{
A a;
int *ptr2x = (int *)&a;
*ptr2x = 10;
char *ptr2c = (char *)ptr2x+4;
*ptr2c = 'A';
char *ptr2s = (char *)ptr2c+1;
strcpy(ptr2s ,"Foo");
a.display();
}
class Test{
int a;
alignas(16) int b;
int c;
};
Test t;
method A : intrusive mood.
since we can access source code and recomplie it, we can use
many other way like friend class to access private member, they are all legal backdoor.
method B : brute mood.
int* ptr_of_member_c = reinterpret_cast<int*>(reinterpret_cast<char*>(&t) + 20);
we use a magic number (20) , and It's not always right. When the layout of class Test changed, the magic number is a big bug source.
method C : super hacker mood.
is there any non-intrusive and non-brute mood ?
since the class Test's layout infomation is hide by the complier,
we can not get offset information from the complie's mouth.
ex.
offsetof(Test,c); //complie error. they said can not access private member.
we also can not get member pointer from class Test.
ex.
&Test::c ; //complie error. they said can not access private member.
#Johannes Schaub - litb has a blog, he found a way to rob private member pointer.
but i thought this should be complier's bug or language pitfall.
i can complie it on gcc4.8, but not on vc8 complier.
so the conclusion may be :
the landlord build all backdoor.
the thief always has brute and bad way to break into.
the hacker accidental has elegant and automated way to break into.
I made Johannes answer more generic. You can get the source here: https://github.com/lackhole/Lupin
All you have to know is just the name of the class and the member.
You can use like,
#include <iostream>
#include "access/access.hpp"
struct foo {
private:
std::string name = "hello";
int age = 27;
void print() {}
};
using tag_foo_name = access::Tag<class foo_name>;
template struct access::Accessor<tag_foo_name, foo, decltype(&foo::name), &foo::name>;
int main() {
foo f;
// peek hidden data
std::cout << access::get<tag_foo_name>(f) << '\n'; // "hello"
// steal hidden data
access::get<tag_foo_name>(f) = "lupin";
std::cout << access::get<tag_foo_name>(f) << '\n'; // "lupin"
}
Call private functions, get the type of private members is also possible with only using the tag.

How to expose fields of a class by name

I want to define structs to hold various application parameters:
struct Params
{
String fooName;
int barCount;
bool widgetFlags;
// ... many more
};
but I want to be able to enumerate, get and set these fields by name, eg so that I can expose them to automation APIs and for ease in serialisation:
Params p;
cout << p.getField("barCount");
p.setField("fooName", "Roger");
for (String fieldname : p.getFieldNames()) {
cout << fieldname << "=" << p.getField(fieldName);
}
Is there a good way of defining a binding from a string label to a get/set function? Along the lines of this (very much pseudocode):
Params() {
addBinding("barCount", setter(&Params::barCount), getter(&Params::barCount));
...
I know that other options are to auto-generate the struct from an external metadata file, and another is to store the struct as a table of (key,value) pairs, but I would rather keep the data in a struct.
I do have a Variant type which all fields are convertible to.
C++ doesn't have reflection so this isn't something you can do cleanly. Also, by referring to members as strings, you have to try to side-step the strongly typed nature of the language. Using a serialization library like Boost Serializer or Google Protobuf might be more useful.
That said, if we allow some horribleness, one could do something with an XMacro. (Disclaimer: I wouldn't recommend actually doing this). First you put all the information you need into a macro
#define FIELD_PARAMS \
FIELD_INFO(std::string, Name, "Name") \
FIELD_INFO(int, Count, "Count")
Or alternatively into a header file
<defs.h>
FIELD_INFO(std::string, Name, "Name") \
FIELD_INFO(int, Count, "Count")
Then you'll define FIELD_INFO inside your class to either mean the member declaration, or adding them to a map
struct Params{
Params() {
#define FIELD_INFO(TYPE,NAME,STRNAME) names_to_members.insert(std::make_pair(STRNAME,&NAME));
FIELD_PARAMS
#undef FIELD_INFO
}
template <typename T>
T& get(std::string field){
return *(T*)names_to_members[field];
}
std::map<std::string, void*> names_to_members;
#define FIELD_INFO(TYPE,NAME,STRNAME) TYPE NAME;
FIELD_PARAMS
#undef FIELD_INFO
};
And then you could use it like this
int main (int argc, char** argv){
Params myParams;
myParams.get<std::string>("Name") = "Mike";
myParams.get<int>("Count") = 38;
std::cout << myParams.get<std::string>("Name"); // or myParams.Name
std::cout << std::endl;
std::cout << myParams.get<int>("Count"); // or myParams.Count
return 0;
}
Unfortunately you still need to tell the compiler what the type is. If you have a good variant class and libraries that play well with it, you may be able to get around this.
I'm using a slightly different storage for this: here. The tags I use are ints for some reason, but you could use std::string keys just as well.
There is no really good way (with "good" being a very subjective aspect anyway), because whatever technique you choose is not part of the C++ language itself, but if your goal is serialisation, have a look at Boost Serialization.
I've managed to come up with something that satisfies my particular need. Ari's answer was closest in terms of mapping strings to references to member variables, though it relied on casting from void*. I've got something that's a bit more type-safe:
There's an interface for an individual PropertyAccessor that has a templated class derived from it which binds to a reference to a specific member variable and converts to and from the Variant representation:
class IPropertyAccessor
{
public:
virtual ~IPropertyAccessor() {}
virtual Variant getValueAsVariant() const =0;
virtual void setValueAsVariant(const Variant& variant) =0;
};
typedef std::shared_ptr<IPropertyAccessor> IPropertyAccessorPtr;
template <class T>
class PropertyAccessor : public IPropertyAccessor
{
public:
PropertyAccessor(T& valueRef_) : valueRef(valueRef_) {}
virtual Variant getValueAsVariant() const {return VariantConverter<T>().toVariant(valueRef); }
virtual void setValueAsVariant(const Variant& variant) {return VariantConverter<T>().toValue(variant); }
T& valueRef;
};
// Helper class to create a propertyaccessor templated on a type
template <class T>
static IPropertyAccessorPtr createAccessor(T& valueRef_)
{
return std::make_shared<PropertyAccessor<T>>(valueRef_);
}
The class exposing a collection can now define an ID -> PropertyAccessor and bind its values by reference:
#define REGISTER_PROPERTY(field) accessorMap.insert(AccessorMap::value_type(#field, createAccessor(field)))
class TestPropertyCollection
{
public:
typedef std::map<PropertyID, IPropertyAccessorPtr> AccessorMap;
TestPropertyCollection()
{
REGISTER_PROPERTY(stringField1);
// expands to
// accessorMap.insert(AccessorMap::value_type("stringField", createAccessor(stringField)));
REGISTER_PROPERTY(stringField2);
REGISTER_PROPERTY(intField1);
}
bool getPropertyVariant(const PropertyID& propertyID, Variant& retVal)
{
auto it = accessorMap.find(propertyID);
if (it != accessorMap.end()) {
auto& accessor = it->second;
retVal = accessor->getValueAsVariant();
return true;
}
return false;
}
String stringField1;
String stringField2;
int intField1;
AccessorMap accessorMap
};