I have class, say Rectangle that has a private method Rectangle::paint. I want to let two other classes access this method, and only those two. So, I thought of this:
template <class T, class Q>
class Rectangle {
void paint();
friend T;
friend Q;
};
Problem is, when I want to instantiate a Rectangle object in T, it means Tneeds to know about Q, either by including a header or by using a forward declaration, both of which I would like to avoid. Also, the other way around regarding Q not knowing about T. Is there a way to do this?
Edit: To clarify a bit, I want to instantiate Rectangle in Foo, but have it mean Rectangle<Foo, Bar> so that Bar could access private members from elsewhere. I don't want Foo to know about Bar or vice versa.
Thanks
If Rectangle is a template and parametrized on Q and T, then Q and T are part of the type. You cannot use Rectangle<Q,T> without "knowing" about Q or T.
How about this:
template <size_t> struct rectangle;
template <size_t tag>
struct rectangle_modifier {
void paint(rectangle<tag>&);
};
template <size_t tag>
struct rectangle {
friend rectangle_modifier<tag>;
private:
void paint() {}
};
template <size_t tag>
void rectangle_modifier<tag>::paint(rectangle<tag>& r) {r.paint(); }
struct foo : rectangle_modifier<1> {};
struct bar : rectangle_modifier<1> {};
int main () {
rectangle<1> r;
foo{}.paint(r);
bar{}.paint(r);
}
foo and bar need not know anything about each other. They both can paint a rectangle<1>. The tag is because you said you want to have different rectangles that each let two different classes access their paint.
Note that this is rather intrusive (foo and bar must inherit), not sure if this is a problem.
Its also not safe in the sense that anybody can write another class that inherits from rectangle_modifier<1> to access rectangle<1>::paint. However, thats not really what private is for. private is to restrict accidential access and to make clear that one should not access it. It is not to prevent by all means that it can be accessed. If someone wants to hack it, they will find a way.
Actually I would simply make rectangle::paint public and call it a day. Encapsulation is to make sure invariants don't break. Painting a rectangle that can be painted does not break an invariant.
Related
My intention is, whenever I add a new derived class, I need it registered in a list of class names in some other class object so that all newly added classes can be used for a process. But doing this without writing something extra to other classes by hand takes more time.
I have lots of derived classes to maintain such as adding them to a list, checking their names and similar things. Now I'm up to make this automated. What I could think of is
have each derived class contain a static member initializer which also adds its own name to base class' static list so that program scheduler parses that list and handles preparations.
look at folder that contains source files(derived class class definitions) with same naming scheme and build a list out of it(again, using names)
have each derived class own a number that is a template type and iterate it in the base class until it gives error
all these may not be suitable for production or at least may not be working at all times, for example, static keyword doesn't work unless a class is used once, but I can't initialize a class if I don't know of. The second choice is not secure, the third I don't know if it could crash the program when integer index of template goes out of border.
How dangerous is to increment
// try until error, can compiler compile this?
while(noError)
{
tryInit(new MyClass<ctr>()).addToList();
}
// or
tryInit(new MyClass<2>()).addToList();
tryInit(new MyClass<3>()).addToList();
tryInit(new MyClass<4>()).addToList();
tryInit(new MyClass<5>()).addToList();
what happens if there are no 5 derived classes?
Is there a beyond static keyword that makes a class load right at the program startup, even without forward declaration or anything else?
What you are describing is possible, if somewhat unsafe/obnoxious
template<int>
struct MyClass : std::false_type {};
template<>
struct MyClass<0> : std::true_type
{
static void foo(int i) { std::cout << i << " is useful!" << std::endl; }
};
// and so on...
To add a new class, just add another specialization of MyClass.
To iterate over all of them
template<int n>
void foo_all_(int i)
{
if constexpr(MyClass<n>::value)
{
MyClass<n>::foo(i);
foo_all_<n + 1>(i);
}
}
void foo_all(int i)
{
foo_all_<0>(i);
}
The unsafe/obnoxious part is that all MyClass has to be properly specialized and defined for this to work.
I would imagine having such a family of classes is useful only with polymorphism, which could make this a bit friendlier
struct Base : std::true_type { /* ... */ };
template<int>
struct MyClass {};
template<>
struct MyClass<0> : Base { /* ... */ };
And hold instances of MyClass with Base references.
I have a custom rather complex data structure with this form:
class Root;
class Tree {
public:
... // lots of members here, child access etc
ExactBar *bar() { return mBar; }
ExactQux *qux() { return mQux; }
private:
... // lots of members here
ExactBar *mBar;
ExactQux *mQux;
};
class Root : public Tree { // root manages the memory for all tree nodes!
...
private:
MemorySpace<Tree> mNodes;
MemorySpace<ExactBar> mBars;
MemorySpace<ExactBar> mQuxs;
};
The purpose of the program is to build the tree for which it requires the exact types above. This requires massive amounts of memory and I'm literally stretched to the 32-bit limit. So I want to, once the tree is built, convert the whole tree to an inexact type which is not only faster, but takes much less memory.
But of course I would like to keep the functionality that Tree offers with its methods, and of course other algorithms that work on Tree. So writing a new class is out of the question. So templates seem very appropriate here. However, I'm wondering about two ways of writing the new, templated class. One obvious way is
template <typename Bar, typename Qux> class Tree {
public:
... // lots of members here, child access etc
Bar *bar() { return mBar; }
Qux *qux() { return mQux; }
private:
... // lots of members here
Bar *mBar;
Qux *mQux;
};
template <typename Bar, typename Qux> class Root : public Tree<Bar, Qux> {
...
private:
MemorySpace<Tree> mNodes;
MemorySpace<Bar> mBars;
MemorySpace<Qux> mQuxs;
};
However this definition seems a bit awkward. I mean, I know I will never use Tree<InexactBar, ExactQux> for instance. Is this bad practice? Sure, you can also solve the long name with a typedef but still. Another solution I thought about is this:
template <typename Exactness> class Tree;
template <> class Tree<Exact> {
public:
... // lots of members here, child access etc
ExactBar *bar() { return mBar; }
ExactQux *qux() { return mQux; }
private:
... // lots of members here
ExactBar *mBar;
ExactQux *mQux;
};
// ... similar for Inexact
Which method is preferable, are there any patterns or anti-patterns or ripple effects doing this that I should be aware of? Thanks!!
Here's another option, that minimizes the number of template parameters and the amount of duplicated code:
struct Exact
{
typedef ExactBar BarType;
typedef ExactQux QuxType;
};
struct Inexact
{
typedef InexactBar BarType;
typedef InexactQux QuxType;
};
template <typename Exactness> class Tree {
public:
typedef typename Exactness::BarType Bar;
typedef typename Exactness::QuxType Qux;
... // lots of members here, child access etc
Bar *bar() { return mBar; }
Qux *qux() { return mQux; }
private:
... // lots of members here
Bar *mBar;
Qux *mQux;
};
This is similar to policy-based design. Of course you still have to templatize all your other functions that deal with the Tree type, so there's still a ripple effect. Although you could partially dodge the ripple effect like so:
template <typename Exactness> class TTree {
... // lots of members
};
typedef TTree<Exact> Tree; // same name as before!
typedef TTree<Inexact> InexactTree;
Another option in addition to #John's is to do explicit instantiation of your template. That is, do not include the template code into your header, but include it in a separate .cpp, and add there an explicit lines on what types do you instantiate with:
template class Tree<ExactBar, ExactQux>;
template class Tree<InexactBar, InexactQux>;
This way the compiler will not link any code using any other instantiation.
If you are pretty sure that these are the only instantiations you would ever need, then this has an additional advantage of decreased compilation time. However, this makes extending the code more difficult: you will have to modify the same .cpp if you want to add new instantiations. This is why I would suggest you using this only if you are pretty sure that you will have the full control on possible instantiations and that the number of this instantiations will not be large.
Ok, so basically I have a class in use in another class which, among other things, asks on object to report on its relationship to another object of the same type. Works great. FYI this class represents a protocol. Unfortunately, now I'm trying to decorate the class relationship by adding a class called a Wrapper. The main power of this class is that it can take the first class as an argument (or anything else that does the same).:
template< class InnerInterpreter >
class WrapperInterpreter
{
public:
WrapperInterpreter(const InnerInterpreter &m) : innerMessage(m) {}
...
virtual bool respondsToMessage(const WrapperInterpreter<InnerInterpreter> &) const = 0;
public:
//member
InnerInterpreter innerMessage;
};
What I've concluded for other design reasons is that having this as a base class to a set of wrappers (rather than taking two different protocols as arguments) allows me a combinatorial set of outer and inner protocol classes.
So here's my problem: When I try to subclass WrapperInterpreter<>, and in particular provide an implementation to respondsToMessage(), I end up with a subclass that is able to compare to any class in the WrapperInterpreter heirarchy. But that's not actually what I want to do. What I would like to do is to force the subclass to implement a method thusly:
template< class Inner >
class ConcreteWrapper : WrapperInterpreter<Inner>
{
...
bool respondsToMessage(const ConcreteWrapper<Inner> &);
...
}
One solution I came to immediately was to simply remove it from the interface of WrapperInterpreter and just let the compiler complain about the missing interface method only when in use with the rest of the design.
So my question is: is there any way to put a method in an abstract class's interface, such that the subclass must take an object of the subclass type as a parameter?
Alternatively, am I trying to use inheritance incorrectly? Does anybody have any useful design patterns that might help me to address this problem?
There is a design called CRTP (Curiously Recurring Template Pattern) which consists in passing the type of the Child to the Parent as a template parameter:
template <typename Child>
class WrapperInterpreter {
using Inner = typename Child::Inner; // nested typedef
WrapperInterpreter(Inner const& ...);
virtual bool respondsToMessage(Child const& ...) = 0;
};
template <typename Inner>
class Concrete: public WrapperInterpreter< Concrete<Inner> > {
virtual bool respondsToMessage(Concrete const& ...) override;
};
I'm trying to create a vector (or any STL container, really) that could hold a set of various objects that are subclasses of one specific type. The problem is that my base class is templated.
From what I can tell, I have to create an interface/abstract super base class (not sure what the preferred C++ terminology is). I'd prefer not to do this, and just use my (templated) abstract base class. Below is some example code.
Basically, is there a way not to require the WidgetInterface? Someway to tell the compiler to ignore template requirements? If I must have WidgetInterface, am I going the right way with the following?
#include <vector>
#include "stdio.h"
enum SomeEnum{
LOW = 0,
HIGH = 112358
};
// Would like to remove this WidgetInterface
class WidgetInterface{
public:
// have to define this so we can call it while iterating
// (would remove from Widget if ended up using this SuperWidget
// non-template baseclass method)
virtual void method() = 0;
};
template <class TDataType>
class AbstractWidget : public WidgetInterface{
public:
TDataType mData;
virtual void method() = 0;
// ... bunch of helper methods etc
};
class EnumWidget : public AbstractWidget<SomeEnum>{
public:
EnumWidget(){
mData = HIGH;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
class IntWidget : public AbstractWidget<int>{
public:
IntWidget(){
mData = -1;
}
void method(){
printf("%d\n", mData); // sprintf for simplicity
}
};
int main(){
// this compiles but isn't a workable solution, not generic enough
std::vector< AbstractWidget<int>* > widgets1;
// only way to do store abitary subclasses?
std::vector<WidgetInterface*> widgets2;
widgets2.push_back(new EnumWidget());
widgets2.push_back(new IntWidget());
for(std::vector<WidgetInterface*>::iterator iter = widgets2.begin();
iter != widgets2.end(); iter++){
(*iter)->method();
}
// This is what i'd _like_ to do, without needing WidgetInterface
// std::vector< AbstractWidget* > widgets3;
return 0;
}
No, you can't use directly AbstractWidget as a parameter of STL container or anything else.
The reason is that class AbstractWidget does not exist. It is only a template for compiler to construct classes from.
What exists is AbstractWidget<SomeEnum> and AbstractWidget<int> only because of EnumWidget and IntWidget inheriting from them.
Templates exist at compiler-level only. If AbstractWidget<T> weren't used anywhere in your code, there would be no traces of it during the runtime.
Therefore, the code you posted seems to be the best (if not only) solution for your problem.
What you've done is the solution: you need a common class/interface, and since AbstractWidget is class template, therefore it cannot be used as common class for all concrete classes for which the template argument is different. So I think, you should go with this class design. It seems to be quite reasonable solution.
In fact the classes AbstractWidget<int> and AbstractWidget<double> are different classes, so your class IntWidget is a subclass of the first but is in no relation with the second. You need to have a common parent class to put in the vector so unfortunately you can not avoid the common interface that is not templated.
This could be completely in the wrong direction, but could you do something like this:
template <class T>
class ConcreteWidget : public AbstractWidget<T>
{
};
and then use template specialization to define your specific widgets like this:
template <>
class ConcreteWidget : public AbstractWidget<int>
{
public:
ConcreteWidget() : mData(-1) {}
};
template <>
class ConcreteWidget : public AbstractWidget<SomeEnum>
{
public:
ConcreteWidget() : mData(HIGH) {}
};
So rather than having an IntWidget and an EnumWidget, you'd have a ConcreteWidget and ConcreteWidget and then could simply have a vector<WidgetInterface> that would be the super of all of these generic children?
I'm not sure if this solves your problem, or would even work. I'd love feedback on this answer.
I really didn't know how to specify the problem in the title, so here's the gist of it.
I am writing graph classes Graph, Node, and Edge, and then subclassing them into VisGraph, VisNode and VisEdge to obtain a drawable graph (in C++). I then need to further subclass those into specific classes that depend on certain data. So I have a lot of parallel inheritance:
Graph -- VisGraph -- RouteGraph
Node -- VisNode -- RouteNode
Edge -- VisEdge -- RouteEdge
This is pretty ugly and I started out doing this, so that I would implement functionality incrementally, but there are a lot of problems. One of them, for example, is that the base class has a container of all the Node instances in the graph. The problem is, if I am in a function in VisGraph dealing with a VisNode, that requires functionality unique to VisNode, I have to do a dynamic_cast on the Nodes that I get from the container in the base class.
Perhaps I should write a "Vis" class that holds a Graph and draws it?
I found inheritance convenient because each node/edge could easily draw itself instead of me
storing extra information outside about position etc. and drawing them all individually.
Do you have any suggestions/design patterns that could make this more elegant?
Thank you in advance.
If in doubt, throw templates at the problem until it surrenders:
template <typename N, typename E>
class Graph {
std::vector<N> nodes;
std::vector<E> edges;
};
typedef Graph<VisNode, VisEdge> VisGraph;
typedef Graph<RouteNode, RouteEdge> RouteGraph;
You lose the inheritance (RouteGraph no longer inherits from VisGraph), but that's normal in C++ for container types, and Graph is somewhat like a container. You can keep the inheritance between Node -> VisNode -> RouteNode, though.
Since nodes and edges are supposed to be of matching types, you could go even further, and give Graph a single template parameter, which itself is a class containing the edge and node types as typedefs. I'm not sure it's worth it, though.
Edit
Since you want to successively add functions, you could keep a form of inheritance but lose the polymorphism:
template <typename N, typename E>
class GraphImpl {
std::vector<N> nodes;
std::vector<E> edges;
};
template <typename N, typename E>
class VisGraphImpl : public GraphImpl<N, E> {
// constructors
// extra functions
};
template <typename N, typename E>
class RouteGraphImpl : public VisGraphImpl<N, E> {
// constructors
// extra functions
};
typedef GraphImpl<Node, Edge> Graph;
typedef VisGraphImpl<VisNode, VisEdge> VisGraph;
typedef RouteGraphImpl<RouteNode, RouteEdge> RouteGraph;
There might be a better way, though, by bundling these extra functions up into sensible mixins and using CRTP:
template<typename Derived>
class VisFunctions {
void somfunc() {
myself = static_cast<Derived&>(*this);
// do stuff
}
};
Then:
class VisGraph : public Graph<VisNode, VisEdge>, public VisFunctions<VisGraph> {
friend class VisFunctions<VisGraph>;
};
class RouteGraph : public Graph<RouteNode, RouteEdge>, public VisFunctions<RouteGraph>, public RouteFunctions<RouteGraph> {
friend class VisFunctions<RouteGraph>;
friend class RouteFunctions<RouteGraph>;
};
Not sure how that'll look for your real circumstances, though. Btw, if you don't want/need the friend declaration for the extra functions, then you don't need those extra functions to be members at all - just make them free functions that take a VisGraph or RouteGraph parameter.