Avoid repeating the template parameter for accessing enum in class template - c++

Consider a class template that implements a container which includes an option for choosing its storage place.
template<class T>
class Container {
public:
enum StorageOption {A,B};
Container(StorageOption opt_): option(opt_) {}
private:
StorageOption option;
};
Here StorageOption was chosen to be a member since it is only used in the class.
Now, to instantiate the class I would need to repeat the template parameter, like:
{
Container<int> c( Container<int>::A );
}
Is there a way to avoid repeating the parameter and at the same time have StorageOption being a member or is there a better way of implementing the option?

It is usually achieved by defining it in a base class.
class ContainerBase {
public:
enum StorageOption {A,B};
};
template<class T>
class Container : public ContainerBase{
public:
Container(StorageOption opt_): option(opt_) {}
private:
StorageOption option;
};
Container<int> c( ContainerBase::A );

I have been battling with this problem myself and I don't really like the need for a base class as well as how you need to repeat the base class specifier when wanting to use enum classes. I came up with this solution:
namespace FuncEnum{
enum class FuncNeighbor{
FLOOR, CEILING, SELF
};
enum class FuncDirection{
BACK, FRONT, BACKNFRONT
};
enum class FuncVar{
X, Y
};
} using namespace FuncEnum;
template<typename... Types>
class Func {};
This way you can have globally available enum classes with minimal specification. It's not likely that collision happens between < class nickname > < enum class name > but even if there were, the using declaration should shadow (?) whatever global identifier about to interfere (which, in a peculiar case can be undone again with another using declaration).

Related

Why can I omit the template parameter specification in some cases?

I have a question as I cannot explain why something works where I probably have made a mistake. Maybe somebody kind can help me to improve my C++ culture by explaining to me why this is so.
For better transparency I simplifiy the code quite a bit.
I have a template virtual class that is like this:
template<class Node>
class tXmlNode
{
public:
tXmlNode();
virtual ~tXmlNode();
protected:
Node* node;
}
;
From this I derive several classes.
Mostly I derive from it another template class such as this one:
template<class Part>
class tXmlMove : public tXmlNode<Part>
{
public:
tXmlMove(Part* part);
~tXmlMove();
protected:
int n_translate;
};
with this implementation (reduced to the constructor):
template<class Part>
inline tXmlMove<Part>::tXmlMove(Part* part) : tXmlNode<Part>(part)
{
//do some construction
}
;
As you can see I delegate some part of the construction to the parent class constructor. Works fine.
Now I have another derived class but which is derived from a specialized parent class (the specialisation is a self-specialisation but from other classes with similar specialized parent it works exactly as for this one):
class tXmlCaseDefinition : public tXmlNode<tXmlCaseDefinition>
{
public:
tXmlCaseDefinition();
tXmlCaseDefinition(const pugi::xml_node& parent);
~tXmlCaseDefinition();
protected:
int n_shapes;
}
;
(I guess it is due to the specialization that I do not need to construct this class as a template class.)
Its not-default constructor is implemented as follows:
nXml::tXmlPart::tXmlPart(
const pugi::xml_node& parent,
const int npos) : tXmlNode(parent, npos), this_id(""), this_type(""), description("")
{
}
;
As you can see I did not delegate to the parent constructor by using tXmlNode<tXmlCaseDefinition>(parent,npos) but simply tXmlNode(parent,npos). I didn't pay attention to that and it works for some mysterious reason. I simply cannot understand why. Can somebody explain?
Also do I need to use tXmlNode<Part>(part) or can I use tXmlNode(part) instead for classes not derived from the specialized parent class or is this only possible when I have a spezialized parent?
Thank you very much!
Within the definition of a template class (more formally, the "current instantiation"), there is something called an injected-class-name, which is simply the name of the template sans arguments. For example:
template<class T>
struct Foo
{
Foo* ptr; // refers to Foo<T>
};
When you derive from a templated class, the base class' injected-class-name is inherited. Therefore you can also refer to the base class sans template arguments (assuming the name is accessible; some ancestor didn't privately inherit from it):
template<class T>
struct Base
{
};
struct Derived : Base<int>
{
Base* ptr; // refers to Base<int>
};
cppreference does a decent job of summarizing all the standardese here (Refer to [temp.local], [basic.lookup], and [basic.scope.class])

C++ template declaration with inheritance list

Is it possible to declare a templated class in C++ along with the classes it inherits from? Basically I want to give the compiler a hint, that my templated class will always inherit another at declaration time.
Maybe some code will clear up why this is a problem for me:
template<typename T>
class GrandparentClass
{
public:
T grandparentMember;
};
//this needs to be only a declaration, since I do not want classes of ParentClass with random T
template<typename T>
class ParentClass : public GrandparentClass<T>
{
};
// this does not work:
//template<typename T>
//class ParentClass : public GrandparentClass<T>;
// this does not either, because then the child class cannot access the variable from the grandparent class
//template<typename T>
//class ParentClass;
template<>
class ParentClass<int> : public GrandparentClass<int>
{
public:
ParentClass()
{
grandparentMember = 5;
}
};
template <typename T>
class ChildClass : public ParentClass<T>
{
public:
void foo()
{
std::cout << grandparentMember << "\n";
}
};
Also, I cannot use C++ 11.
EDIT:
I found an easy way out of this:
template<typename T>
class ParentClass : public GrandparentClass<T>
{
public:
ParentClass() { ParentClass::CompilerError(); };
};
Just do not define CompilerError() method in the class and everything's fine.
A class declaration is only really useful for non-value variable declarations, like pointers and references. You can't access the class members or even instantiate it, though. Even if you knew that a declared class inherits from some other one, you still wouldn't necessarily be able to utilize that information in any way.
As such, it's only important for the compiler to know what the class inherits from once it learns its full definition.
After clarification in comments: if you want to prevent instantiation of a class template with some types, its definition is the place to do it. A simple static_assert inside the class body will do the trick; Boost.StaticAssert or older SFINAE tricks will do the job for pre-C++11 code.
If you are happy with delaying the error to link-time, rather than compile time, you can declare all the member functions of parent in parent.h, provide definitions in parent.cpp, and explicitly instantiate the finite list of classes that you want.
Parent.h
template<typename T>
class ParentClass : public GrandparentClass<T>
{
ParentClass();
};
class ParentClass<int>;
class ParentClass<long int>; // or whatever
Parent.cpp
template <typename T>
ParentClass::ParentClass() : grandparentMember(5) {}

Make sure only Smartpointers are build

I want to make sure only smart pointers are build from my classes so i made all constructors protected.
To create objects i build this "Buildable"-Policy:
template <typename T>
class Buildable
{
public:
template<typename ...Args>
static QSharedPointer<T> buildObject(Args&&... all)
{
return QSharedPointer<T>( new T(std::forward<Args>(all)...) );
}
};
If i use this this policy in a base class, all goes well.
But when i use it in base and a derived class like this:
class A : public Buildable<A> {}
class B : A, public Buildable<B>{}
the compiler argues: Error: member 'buildObject' found in multiple base classes of different types
I don't know how to solve this problem. Any ideas?
Cause of the error
This is because the multiple inheritance here:
class B : A, public Buildable<B>{};
It causes class B to inherit from Buildable<A> and from Buildable<B> which both contain a buildObject() overload. Unfortunately, both overloads differs only by the return type. This is not allowed.
Design issue
Unfortunately, you can't avoid this unless you could smuggle an additional parameter to buildObject(), which could permit the compiler to use proper type derivation to resolve avoid ambiguity.
But do you really intend to have multiple inheritance in your design here ? If your classes would be polymorphic, couldn't you use a class B defined as follows:
class B : public A {}; // inherits from Buildable A
...
QSharedPointer<A> b = B::buildObject(); //
Alternative design
The alternative could be to put the building class at the bottom of the derivation, to avoid the conflicts. Make your constructors for classes A and B protected, and use this template class :
// (I used here shared_ptr instead of QSharedPointer for testing purpose)
template <typename T>
class Builder : public T
{
public:
Builder() = delete;
Builder (const Builder&) = delete;
template<typename ...Args>
static shared_ptr<T> buildObject(Args&&... all)
{
return make_shared<T>(std::forward<Args>(all)...) ;
}
};
class A { };
class B : public A {}; // Normal class hierarchy.
// can't be instantiated if ctor are protected.
shared_ptr<A> a = Builder<A>::buildObject();
shared_ptr<B> b = Builder<B>::buildObject();
One easy solution to the design problem is to make buildObject a freestanding function template, that you make a friend of each user class.
In order to simplify friend declarations you may want to put that function template in a class.
Then it's very much like your existing code, except there's no inheritance from the factory class:
#include <memory> // std::shared_ptr
#include <utility> // std::forward
namespace my{
using std::forward;
using std::shared_ptr;
template< class Class >
struct Make_
{
template< class... Args >
static auto instance( Args&&... args )
-> shared_ptr<Class>
{ return shared_ptr<Class>( new Class( forward<Args>( args )... ) ); }
};
class A
{
template< class > friend struct Make_;
protected:
A( int ) {}
};
class B
: public A
{
template< class > friend struct Make_;
protected:
B( int x ): A( x ) {}
};
} // namespace my
auto main() -> int
{
using namespace my;
auto p = Make_<B>::instance( 42 );
}
General solutions to the immediate technical problem of providing a covariant function without repeating its definition, include:
A macro (that expands to the function definition).
This is what I recommend, if you feel that it absolutely has to be a member function. It's one of the few legitimate uses of macros.
Middle-man inheritance.
Essentially instead of inheriting directly from a Base and also from a mixin, you inherit from the mixin and ask it to inherit from Base. You need to forward constructor arguments from the mixin.
Dominance in virtual inheritance hierarchy.
A really ugly and complex solution. Don't go there. But it's a technical possibility.
Finally there is non-solution of using a function that returns a (smart) pointer to base class. Where the client code has to cast it down. It's really ungood in its own way, but I mention it for completeness.
You could inherit from QEnableSharedFromThis (see here for further details).
As an example:
class C: public QEnableSharedFromThis<C> {
C() = default;
// all the other constructors
public:
template<typename ...Args>
static QSharedPointer<C> create(Args&&... all) {
// refers one of the available constructors
return QSharedPointer<C>(new C{std::forward<Args>(all)...});
}
QSharedPointer<C> getSharedFromThis() {
return sharedFromThis();
}
};
You can use it as a base class for your hierarchy.

How to achieve code reuse with nested enums

I'm trying to build a class such that its subclasses will have a C++11 enum class attribute, with an associated setter/getter:
class Base {
public:
enum class MyEnum {
A,
B
} my_enum;
Base() : my_enum(MyEnum::A) {}
MyEnum get() { return my_enum; }
void set(const MyEnum &ME) { my_enum = ME; }
};
class Derived : public Base {
public:
Derived(): Base() {
my_enum = MyEnum::B;
}
};
int main(int argc, char *argv[])
{
Derived Deriv;
// No problems!
Deriv.get() == Derived::MyEnum::B;
return 0;
}
so far, so good!
However, I would like derived classes to be able to re-define the MyEnum enumeration class, while not having to re-implement the setter/getter/attribute all the time:
// Base as before
class Derived : public Base {
public:
enum class MyEnum {
C,
D
}; // intention: to override Base's "my_enum" attribute
Derived(): Base() {
my_enum = MyEnum::C;
// ERROR: cannot convert 'Derived::MyEnum' to 'Base::MyEnum'
}
};
int main(int argc, char *argv[])
{
Derived Deriv;
// ERROR: no match for 'operator==' for types 'Base::MyEnum' and 'Derived::MyEnum'
Deriv.get() == Derived::MyEnum::C;
return 0;
}
I understand what the problem is; I'm just looking for the cleanest way to be able to reuse code for this case.
Preferably only through inheritance (or rather, the functionality should be available to Derived() classes solely by the act of deriving from Base()).
Any suggestions?
You could make Base a template, parameterised by the enum type, and use a traits class to provide a "default" enum type which can be specialized by derived types.
template<typename T>
struct MyEnumTraits
{
enum class type {
A,
B
};
static const type default_value = type::A;
};
template<typename T = void>
class Base {
public:
typedef typename MyEnumTraits<T>::type MyEnum;
MyEnum my_enum;
Base() : my_enum(MyEnumTraits<T>::default_value) {}
MyEnum get() { return my_enum; }
void set(const MyEnum &ME) { my_enum = ME; }
};
class Derived;
template<>
struct MyEnumTraits<Derived>
{
enum class type {
C,
D
};
static const type default_value = type::C;
};
class Derived : public Base<Derived> {
// ...
But now different derived types will have different base classes, which is probably not what you want. You could solve that by keeping the non-template Base and moving the getter and setter into an intermediate class template that derivecs from Base and then the derived types derive from that.
class Base { ... };
template<typename T = void> class GetterSetterImpl : public Base { ... };
class Derived : public GetterSetterImpl<Derived> { ... };
The compiler is right: although the enumerations Base::MyEnum and Derived::MyEnum are defined in classes connected through inheritance, the enumerations themselves are not considered related. They just happen to have the same unqualified name, which means nothing to the compiler: as far as the compiler is concerned, the two enum types are unrelated.
If you think about the way the enums are implemented under the hood, this makes sense: despite being strongly typed, the enums remain small integral constants. Since the two are unrelated, Base::MyEnum::A would have the same value as Derived::MyEnum::C, and there would be nothing at runtime letting you distinguish between the two values.
Besides dumping all enumeration values into the enum of the base class (which kills opportunities to extend outside your own library) there is little you can do: C++ enumerations do not support inheritance, and are generally not very flexible.
This is a bad idea and is not going to work.
Language level You cannot redefine stuff in C++. You can only hide (not completely) stuff behind new, unrelated stuff with the same name. You can also override a virtual function by giving it a new implementation, while keeping its signature.
Design level Your base class defines a contract which derived classes must adhere to. If Base::get() returns a MyEnum {A, B}, then every derived class must have a get() that returns a MyEnum {A, B}. That's what inheritance is all about (and not code reuse, or not just code reuse at any rate).
You may be able to achieve code reuse by making your class into a template instead of relying on inheritance.

C++ Class inheriting from template class without knowing the type?

I am designing a template class Policy which needs to be able to handle pointers to other classes.
template <class P>
class Policy
{
private:
const P *state;
public:
Policy (P const* s) : state(s){};
};
This works fine.
Now I want to inherit from the above template class and create new subclasses:
class Greedy : public Policy<???>
{
public:
template <typename P> Greedy (P const* s) : Policy(s) {}:
};
class Explora : public Policy<???>
{
public:
template <typename P> Explora (P const* s) : Policy(s) {}:
};
Problem is that when defining those classes I do not know what type they will be using for the base template class. Is this even possible to do ?
I want the type obtained from the inherited class constructor (probably templated), and then pass it to the base class construtor.
Can I do that ? If yes, how ? typedefining enums ?
I have seen this question but it doesn't in my opinion really answer the question.
Make them template classes:
template <typename P>
class Greedy : public Policy<P>
{
// now you know
};
You can certainly do it (see GMan's answer for the correct parametrization of the derived type), but bear in mind that you will get entirely independent class hierarchies for every type P. You are not magically creating a super class that has an arbitrary number of member types.
Consider templates as a code generation tool. They do not create a "type-generic type", rather they create lots of parallel instances of concrete, static types at compile time following a generic pattern.
If you truly want one single common base type, perhaps you can make the type of state polymorphic:
class Policy // no template
{
StateBase * state;
public:
Policy(StateBase * s) : state(s) { }
};
Then all your derived classes can access the states' common interface.