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.
Related
My task is to create a priority queue template class and show its work using different data types: int, string and any struct. I have to add, delete, print a specific element.
The class is:
template< class Type >
class PriorityList
{
private:
List<Type> elems;
As a struct I picked was this:
struct SOMESTRUCT
{
int num;
char word[];
};
As I understand a template class is a universal class which can be used for any incoming data type. I can see how to create the class for int and char [], but how do I make it work for struct too? Since you can't just write cout<< struct, neither cin>>... I'd have to create another function for inputting/outputting my struct, but if I put it in my template class, the class wouldn't be universal again.
What do I do? Also, do I have to make template or leave just one typename?
You can use
template<typename C>
class PriorityList
{
// ...
};
for any type C, including int, char, SOMESTRUCT. I would recommend against using cin and cout in your template, since it makes it harder to use for any class. You would need to overload operator<< and operator>> for each class you use, which might be tricky.
Instead you should just define some simple member functions. I would try to copy the style of std::queue<T>, since people will be familiar with it.
For example:
template<typename C>
class PriorityQueue
{
public:
void push(const C& item, int priority=0){
// ...
}
C& front(){
// ...
}
// and other required functions
};
Once it is defined, you can test it for different classes however you want. You can e.g. create a main() to declare a PriorityQueue<int>, read some ints from std::cin and then call those functions you defined, or you can just declare some instances of SOMESTRUCT and pass them into a PriorityQueue<SOMESTRUCT>.
In a real-life project you would probably use a proper unit testing framework such as catch for this purpose, which would automatically check everything works.
I have some macros that need access to the type of the current class and I currently get away with this via a DRY-violating pattern:
struct ThisScruct{
int a;
double b;
//example static method using this - purely example - not full usecase
static size_t sum_offsets(){
typedef ThisStruct SelfT;
return offsetof(SelfT, a) + offsetof(SelfT, b);
}
};
This comes up a lot with use of the offsetof keyword, at least in my own work.
Now before you lock onto this not being accessible via a static method - realize I just want to know how to get the type ThisStruct in a generic/macro friendly way from a static method context. I don't actually need/want an instance and am looking for way that actually works like the above without typedeffing SelfT.
Edit: Something similar is asked in Can I implement an autonomous self member type in C++? - but I am worried about a diamond problem forming with classes both inheriting from the accepted answer's Self class.
You could use the CRT-pattern to access the typename generically, you just need to specify it in the inheritance list.
template<class T>
struct Type { using type = T; };
struct ThisScruct : Type<ThisStruct> {
int a;
double b;
// this function can be copy-pasted into every
// struct definition, which is inherited from
// Type and contains the members a and b
static size_t sum_offsets(){
typedef Type::type SelfT;
return offsetof(SelfT, a) + offsetof(SelfT, b);
}
};
You might rename Type to a more descriptive name. But you might consider replacing this functionality completely by the CRT-pattern, by moving the functions into the inherited struct.
template<class T>
struct SumOffsets {
static size_t sum_offsets(){
typedef T SelfT;
return offsetof(SelfT, a) + offsetof(SelfT, b);
}
};
struct ThisStruct : SumOffsets<ThisStruct> {
int a;
double b;
};
The function sum_offsets can be accessed by ThisStruct::sum_offsets, because even static functions are inherited. There is no additional overhead, because neither virtual functions are involved nor SumOffsets has data members.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
(This question is related to reflection, but isn't really about reflection)
I have this hierarchy of classes (say class A and class B : public A), and in addition to instance-specific data, I'd like to have class-specific data shared by all instances. For example, suppose I want to have a FunnyClassName string for each of my classes.
I would like to be able to have non-virtual getters for my per-class data, such as:
/*can it be static? */ const std::string& A::GetFunnyName();
and the most important thing is that I want to have no, or as little as possible, boilerplate code in inheriting classes. The getters are to be implemented once in class A (the root of the class hierarchy); class B should specify its FunnyClassName some other way.
It's been suggested (e.g. indirectly in questions here on SO) that a Multiton object, using the class' type hash as a key, might be the basis of a reasonable solution. Is that the case? Is there 'standard' code which does this (e.g. in the STL or in Boost)? Is there another relevant approach?
Notes:
Think this is impossible? See this question and this (laconic) answer. But as some commenters and responders suggest, it may be necessary to have non-static getters, and make the weaker constraint of not having to rewrite the getter for every class (i.e. using RTTI).
If C++ had static virtual data members, this would be trivial - virtual static const std::string FunnyName. With static virtual methods it would also be possible but only if we drop our demand for the getter only being implemented in the base class. We would have something like /* static??*/ static const std::string& A::GetFunnyName() { return "Aye"; } and /* static??*/ const std::string& B::GetFunnyName() { return "Bee"; }.
I'm not particularly interested in the case of templated classes, but if you want to address that as well, that's nice.
FunnyName() is just an example. It could be const Thing& GetFunnyThing(). I don't want anything like the class' name from typeid.name(), or its demangling, or such.
C++11 is ok, but a solution in C++03 would be better. No C++14 please.
If you don't want to use virtual, you can use templates. The name of this idiom is Curiously recurring template pattern, and it's used in ATL and WTL.
Look code.
#include <iostream>
#include <string>
template <typename C>
class Super
{
public:
std::string GetFunnyName() const
{
C *thiz = static_cast<C *>(this);
return thiz->GetFunnyName();
}
};
class A : public Super<A>
{
public:
std::string GetFunnyName() const
{
return "A";
}
};
class B : public Super<B>
{
public:
std::string GetFunnyName() const
{
return "B";
}
};
template <typename TSuper>
void OutputFunny(const TSuper &obj)
{
std::cout << obj.GetFunnyName() << "\n";
}
int main()
{
A a;
B b;
OutputFunny(a);
OutputFunny(b);
}
(live example)
If you want to make B inherit A, code like this:
template <typename C>
class A_base : public Super<C>
{
...
};
class A : public A_base<A> { };
class B : public A_base<B>
{
...
};
(live example)
My example code uses compile-time polymorphism. So, it cannot be applied in runtime. If you want to get "FunnyName" in runtime, you should use virtual, run-time polymorphism.
Curiously recurring template pattern works like this:
You may see the basic form of the pattern.
template <typename C>
class Super
{
void foo()
{
C *thiz = static_cast<C *>(this);
thiz->foo();
}
...
};
class Derived : public Super<Derived>
{
void foo()
{
std::cout << "fooo!!\n";
}
...
};
The derived class inherit Super, with Derived itself as template parameter.
Super<Derived> is concretized like this:
template <>
class Super<Derived>
{
void foo()
{
Derived *thiz = static_cast<Derived *>(this); // 1
thiz->foo(); // 2
}
};
On 1, we're casting this pointer into Derived *, and call foo with this casted pointer on 2. Since the type of pointer is Derived *, thiz->foo(); statement will call Derived::foo.
(wikipedia page explanation seems good)
Your (original) question is ill-posed (or can be answered by this is impossible). One the one hand you want The getters are to be implemented once in class A (the root of the class hierarchy) and that's that. On the other hand you suggest that If C++ had static virtual data members, this would be trivial. However, with static virtual methods you still would need to re-implement the getters for each derived class, contradicting your first request.
I have implemented some code with the same aim, i.e. giving a nice name description for each class.
namespace some_namespace {
/// demangles symbol name as returned by typeid(T).name()
std::string demangle(const char*mangled_name);
inline std::string demangle(std::string const&mangled_name)
{ return demangle(mangled_name.c_str()); }
/// provides the name for any type
template<typename T>
struct name_traits
{
private:
template<typename U, U> struct check;
template<typename U>
static std::true_type test(check<std::string(*)(), &U::name_of_type>*);
template<typename U>
static std::false_type test(...);
// NOTE what_type required to trick icpc 14.0.2 to compile
typedef decltype(test<T>(0)) what_type;
/// true if static std::string T::name_of_type() exists
static constexpr bool has_name_of_type = what_type::value;
/// return name of types with static std::string name_of_type()
template<bool S>
static enable_if_t< S, std::string>
name_t() { return T::name_of_type(); }
/// return name of all other types: demangle typeid(T).name();
template<bool S>
static enable_if_t<!S, std::string>
name_t()
{ return demangle(typeid(T).name()); }
public:
static std::string name()
{ return name_t<has_name_of_type>(); }
};
}
/// macro returning the name of a given type.
#define nameof(TYPE) some_namespace::name_traits<TYPE>::name()
Here, any type A may be equipped with std::string A::name_of_type(); to provide the info, or a specialisation struct some_namespace::name_traits<A> may given. If neither is the case, the name is picked up from demangling the typeid.
I am not sure this answers the question, but you should consider using typeid. This is a part of RTTI, so it can distinguish static and dynamic types.
Have the following code in your base class:
struct A {
...
std::string GetFunnyName() {return typeid(*this).name();}
};
The strings returned for different derived classes will be different; however, you don't have any control on what these strings will look like (they may contain e.g. a mangled version of the type name).
You may want to use a std::map to translate these system-generated names into more preferred ones like FunnyName1, FunnyName2 etc, but you cannot extract the name of the derived class (or maybe you can, but not in a portable way).
Here is a demo.
Edit: since you really want to work with FunnyThing and not with FunnyName, you should definitely use a map. Make it a static object:
struct A {
private:
static std::map<std::string, Thing*> my_map;
...
}
Then use it to convert string to Thing:
struct A {
...
public:
Thing& GetFunnyThing() {return *my_map[typeid(*this).name()];}
...
};
Now each derived class should use RegisterThing to "declare" which Thing it wants to return.
struct A {
...
protected:
static void RegisterThing(std::string name, Thing* thing) {my_map[name] = thing;}
...
}
Calling this method only once, and at the correct time, can be implemented in different ways (like the Singleton pattern can be), so I don't want to complicate matters by giving an example.
I am trying to make a template class as placeholder class which can hold something like and string and type T object. Below is the code which I have written for the same.
#include <iostream>
#include <string>
#include <map>
using namespace std;
//A class which act as placeholder to hold
//unknown object. Something similar as Object
//in Java
template <typename T>
class Genric
{
public:
map<string, T> addP; //This will be placeholder for time
// being.
};
class A
{
public:
Genric t1; //Have object of Genric class so that we can
// access the member variable in future.
void foo()
{
cout<<"Calling foo"<<endl;
}
};
int main()
{
A a1;
a1.foo();
}
But when I tried to compile I am getting below error.
$ g++ tempClass.cxx
tempClass.cxx:21:9: error: invalid use of template-name 'Genric' without an argument list
The purpose of above Genric class is just to act as placeholder class for one of the member variables which can be populated in future.
So is there a way we can write such Genric class.
You are defining Genric as a template class, but then trying to initialize t1 without giving a type to it. That is the error you are getting. Try for example:
Genric<int> t1;
Or, if you are looking for a truly runtime generic, look into boost::any.
You need something like boost::any:
map<string, boost::any> anywayzz;
You can store any object in it. You don't need Genric class template.
If you're not using boost, then you can implement any yourself. Look for its implementation, or type-erasure, on this site. You will surely get some idea. Start from here:
Type erasure techniques
A template is "generic" until the program is compiled. At that point the compile must be made aware of what types it has to deal with.
If you want something that can contain a compile-time unknown (better: not yet known) type template are not the solution. Since the actual type will be known just at runtime, you have to go towards runtime-based polymorphism (inheritance from a polymorphic base) eventually wrapped inside an "handler".
In essence you need a base with at leas t a virtual function that allow you to check the type, and generic derived class that implement that function in a suitable way for all types.
boost::any can be an implementation, but there can be simpler ways, especially considering that "a function that allows to discover a runtime type" is no more than ... dynamic_cast.
You can so cometo a solution like this
#include <memory>
class any_value
{
template<class T>
class wrapper; //see below
class common_base
{
public:
virtual ~common_base() {} //this makes the type polymorphic
template<class T>
T* has_value()
{
auto* ptr = dynamic_cast<wrapper<T>*>(this);
return ptr? &ptr->m: nullptr;
}
};
template<class T>
class wrapper: public common_base
{
public:
wrapper() :m() {}
wrapper(const T& t) :m(t) {}
T m;
};
std::unique_ptr<common_base> pb;
public:
any_value() {}
template<class T>
any_value(const T& t) :pb(new wrapper<T>(t)) {}
template<class T>
any_value& operator=(const T& t)
{ pb = std::unique_ptr<common_base>(new wrapper<T>(t)); return *this; }
any_value(any_value&&) =default;
any_value& operator=(any_value&&) =default;
//NOW THE GETTERS
template<class T>
T* get() const //nullptr if not holding a T*
{ return bool(pb)? pb->has_value<T>(): nullptr; }
template<class T>
bool get(T& t)
{
T* pt = get<T>();
if(pt) t = *pt;
return bool(pt);
}
};
#include <iostream>
#include <string>
int main()
{
any_value a(5), b(2.7192818), c(std::string("as a string"));
int vi=0; double vd=0; std::string vs;
if(!a.get(vi)) vi=0; //will go
if(!a.get(vd)) vd=0; //will fail
if(!a.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!b.get(vi)) vi=0; //will fail
if(!b.get(vd)) vd=0; //will go
if(!b.get(vs)) vs.clear(); //will fail
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
if(!c.get(vi)) vi=0; //will fail
if(!c.get(vd)) vd=0; //will fail
if(!c.get(vs)) vs.clear(); //will go
std::cout <<"vi = "<<vi<<", vd = "<<vd<<", vs = "<<vs<<" \n";
}
Following Abhinav comment:
Since the C++ type system is static, you cannot -in general- deserialize an "unknown", unless you first deserialize something that can be "Known".
For this you first need a way to represet a C++ type (not object) into an recognizable value (sort of type-uid), and a "factory" that creates the wrappers appropriated for those "values".
On saving, you just save that uid, then ask via a common_base virtual function to save the wrapped value.
On loading, you first load the uid, than create a new wrapper with appropriate type (see after) and than load the value via a common_base virtual function.
To create an appropriate wrapper, you need a table that maps the uid-s towards functions that create the wrapper associated with the type uid.
This table must be pre-initialized for all the types you need to be able to serialize / deserialize.
But this goes long away your original question, that doesn't speak about serialization/deserialization.
If the problem is "serialization", the "type erasure" is not a complete solution. You should much more look at the "factory pattern". And post another question better suited for that argument.
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