How to force use of curiously recurring template pattern in C++ - c++

I have the following base template class.
template<typename T>
class Base {
public:
void do_something() {
}
};
It is intended to be used as a curiously recurring template pattern. It should be inherited like class B : public Base<B>. It must not be inherited like class B : public Base<SomeoneElse>. I want to statically enforce this requirement. If someone uses this wrong, I expect an error in the compiling phase.
What I'm doing is putting a static_cast<T const&>(*this) in do_something(). This way the class inheriting the template is or inherits from the class provided as the template parameter. Sorry for the confusing expression. In plain English, it requires B is or inherits from SomeoneElse in class B : public Base<SomeoneElse>.
I don't know if it's the optimal way to achieve this. Looks gross to me.
However I want to do more. I want to ensure B is SomeoneElse itself. How can I do that?

Make the constructor (or destructor) of Base private, and then make T a friend. This way the only thing that can construct/destruct a Base<T> is a T.

If your class contains some code that says:
T* pT = 0;
Base *pB = pT;
Then there will be a compiler error if T is not assignment-compatible with Base.
This kind of check is formalised in C++11 so you don't have to write it by hand and can get helpful error messages:
#include <type_traits>
template<typename T>
class Base {
public:
void do_something()
{
static_assert(
std::is_base_of<Base, T>::value,
"T must be derived from Base");
}
};
class B : public Base<B> { };
int main()
{
B b;
b.do_something();
}
As to ensuring that Base's type parameter is exactly the class that is deriving from it, that seems conceptually flawed. A class that is acting as a base class can't "talk about" the type that is inheriting it. It may be inherited more than once via multiple inheritance, or not at all.

Two good answers so far. Here is another which uses the idiom of generating custom access keys to certain methods (in this case a constructor). It provides an absolute guarantee of correct use while not exposing private methods in the base to the derived.
It can also be used to control access to other methods in the base class on a case-by-case basis.
template<class Derived>
struct Base
{
private:
// make constructor private
Base() = default;
protected:
// This key is protected - so visible only to derived classes
class creation_key{
// declare as friend to the derived class
friend Derived;
// make constructor private - only the Derived may create a key
creation_key() = default;
};
// allow derived class to construct me with a key
Base(creation_key)
{}
// other methods available to the derived class go here
private:
// the rest of this class is private, even to the derived class
// (good encapsulation)
};
struct D1 : Base<D1>
{
// provide the key
D1()
: Base<D1>(creation_key())
{}
};

Related

Is there a way to forbid a base class method call in the derived class?

In c++ "protected" modifier allow method calls only in derived classes. Is it possible to implement inverse logic - prohibit calling a base class method in the derived classes? The code below illustrates what I want to get.
class Base
{
int data;
protected:
// This constructor should be called only in the derived classes
Base(int d): data(d) { }
public:
// This construcor can be called wherever except a derived classes!
Base(): data(0) { }
};
class Derived : public Base
{
public:
// The developer must not forget to initialize "data"
Derived() : Base(10) {}
// I want to get a compilation error there
Derived() : Base() {}
};
Is it possible to [...] prohibit calling a base class method in the derived classes?
Yes. By using private access specifier. Private names are accessible only to the class itself.
It is not inverse logic however. It is not possible for reduce accessibility of of otherwise public name from derived classes.
// This construcor can be called wherever except a derived classes!
There is no way to do this. A public function can be called by anyone and there is no SFINAE trick you can use to stop it if it is called by a derived class since the constructor has no idea where it is called from.
This seems like a XY problem. Although I do not recommend this (I recommend rethinking the design) I found (for better or worse) a solution inspired from the CRTP pattern:
template <class D = void>
class Base
{
protected:
int data;
protected:
// This constructor should be called only in the derived classes
template <class Der = D, class = std::enable_if_t<std::is_base_of_v<Base, Der>>>
Base(int d): data(d) {}
public:
// This constructor can be called wherever except a derived classes!
template <class Der = D, class = std::enable_if_t<!std::is_base_of_v<Base, Der>>>
Base(): data(0) { }
};
class Derived : public Base<Derived>
{
int mydata = 1;
public:
// The developer must not forget to initialize "data"
Derived() : Base(24) {}
// I want to get a compilation error there
//Derived() : Base() {} // (1) compilation error here
};
auto test()
{
Base b1{};
//Base b2{24}; // (2) compilation error here
Derived d{};
}
Of course there are problems with this. For starters there is nothing stopping from creating a derived class as class Derived : public Base<void>.
And if you want, you can add a common base class
class Base_l0
{
};
template <class D = void>
class Base_l1 : Base_l0
{
};
class Derived : public Base_l1<Derived>
{
};
The short answer is no.
In C++, there is only public protected and private. There is no middle ground. Your functions are either accessible from everywhere (public), from nowhere except the class itself (private), or from the class and its children (protected).
I only want to force the user to perform some additional actions wlile inheritting [sic]. For example, to avoid random errors.
If calling the default constructor causes errors by calling it while inheriting from it, then then it is probable it causes errors when you are not inheriting from it. That means you probably shouldn't have this constructor as public anyway, if at all.

Enforce a protected constructor in deriving class

Is there any mechanism that allows to enforce a protected constructor in a deriving class?
Simple example:
template<typename T>
class Factory;
class Base {
template<typename T>
friend class Factory;
protected:
Base();
};
class Child : public Base {
public:
Child(); // this should lead to a compile time error
};
<template T>
class Factory {
Base* GetNew()
{
BOOST_STATIC_ASSERT(boost::is_base_of<Base, T>::value);
Base* b = new T();
b->doStuff();
return b;
}
};
So I want the Child class to be only creatable by the factory and enforce that all child classes deriving from Base have a protected constructor.
No, there's no way to enforce this. In general, base classes are very limited in how they can constrain subclasses. Base is not, and should not try to be, responsible for policing everyone who might ever write a class that happened to inherit from Base.
Short answer, no kind of.
protected is the least useful access specifier since any derived class is free to make the name (including the name of a constructor) public.
What you can do is use an access key in the constructor to ensure that only a factory creates the class.
struct factory;
// create_key's constructor is private, but the factory is a friend.
class create_key
{
create_key() {};
friend factory;
};
struct only_from_factory
{
// base constructor demands a key is sent. Only a factory may create a key.
only_from_factory(const create_key&) {};
};

Access on base class of template prior to expansion of the template being derived from

I'm trying to publicly derive a class from a template that will make it inherit from a base class and get access on protected members. But before the template is expanded it doesn't have those rights, so it can't use a Base member as a template parameter:
using Fun = void (*)();
class Base {
protected:
// friend class Derived; // ...need this to eliminate complaint
static void something();
};
template<Fun F>
class Variant : public Base {};
class Derived : public Variant<&Base::something> { // `something()` is protected
public:
void somethingElse() {
something(); // doesn't complain about this `something()`
}
};
int main() {}
The weird bit about this to me was that friending it worked at all. I wondered if I might "sneak Derived in the door" by putting a public virtual inheritance from Base before the Variant:
class Derived : public virtual Base, public Variant<&Base::something>
That didn't help.
Question: is there some other trick for avoiding explicit mention of all derived classes in Base, yet still have access to pick protected members out of it for template parameters?
(Note: Trying this on an older gcc, 4.6.3, looks like even the friending doesn't help in that case. So it seems support for that is somewhat new.)
Stick the offending access into a metafunction. Derive the metafunction class from the base.
template<typename B>
struct something_variant : public B {
typedef Variant< & B::something > type;
};
class Derived : public something_variant<Base>::type {
…
http://coliru.stacked-crooked.com/a/6bca00455bd3daca
Regarding CWG 372, the critical text in the resolution is this:
[A]ccess checking of base-specifiers must be deferred until the entire base-specifier-list has been seen.
This was already accepted in C++11, so it's interesting that your example is rejected. And, plugging the relevant example code from the C++11 standard into recent Clang and GCC demonstrates that they simply did not implement the deferral. It's at least a little unsurprising, since implementation requires some data structure to represent a set of deferred access checks… fairly high effort for a corner case.

c++ How do you call a templated base-class function from derived class instance

Found related questions but not the exact variant so I am posting a very simple question.
A derived class inherits from a templated base, and I want to call the base function, how to do it?
template <class A>
class testBase {
public:
void insert(const A& insertType) {
// whatever
}
};
class testDerived : testBase<double> {
// whatever
};
int main() {
testDerived B;
// Compiler doesn't recognize base class insert
// How do you do this?
B.insert(1.0);
}
Need public inheritance (default is private for class):
class testDerived : public testBase<double> {
A class has a default access level of 'private'. You basically inherited 'testBase' using private inheritance so that testBase's public interface is not part of testDerived's. Simple solution:
class testDerived: public testBase<double> {...};
I do wish C++ applied public inheritance by default though since that's generally a much more common case. Then again, we could just all use structs instead. :-D

How to force all derived classes to implement a virtual method?

Say you have a base class Dep for a tree of classes. There is a virtual method Dep* Dep::create() that I want to be implemented by every single leaf class. Is there any way to enforce this?
Note: The problem here is that there could be intermediate classes (say class B : public A : public Dep) implementing this method (A::create) by accident or because they think they are leaf classes, but are in fact subclassed themselves.
The question ends here.
Context
If you are curious why I need this; I have a class Master which has Dep objects of unknown concrete type. If Master is duplicated, I need to come up with a matching clone of the Dep instance. Next best thing to do is the virtual constructor idiom, which introduces precisely this problem.
Additionally, I cannot even catch this (other then by crashing horribly), because for obscure reasons, people that have more to say than me, have outlawed dynamic_cast in this project (perhaps this is a good decision; But anyways a completely different discussion).
C++ provides no way to keep a class from inheriting from your class, and there is no way to make a particular class in the inheritance hierarchy implement a method. The only rule is that somewhere in the inheritance hierarchy above a particular class (not necessarily in the leaf) all virtual functions must have an implementation for that class to be instantiatable.
For instance, A could inherit from Def and implement all it's [pure] virtual methods. Then if B inherits from A, it doesn't have to implement anything. There's no way to keep that from happening.
So the answer is no, there is no way to enforce this.
Using curiously recurring template fun, you can achieve something quite similar:
template<typename T>
class Cloneable : public T, public Dep
{
private:
Cloneable<T>() : T() { }
public:
static Cloneable<T>* Create() { return new Cloneable<T>(); }
Cloneable<T>* clone() { return new Cloneable<T>(*this); }
};
Instead of deriving from Dep and instantiating via new MyType, use Cloneable<MyType>::Create. Since Cloneable<MyType> is derived from MyType, you can use the instance the same way you would use any MyType, except that it is now guaranteed to have Dep::clone.
Additionally your Master should not accept an instance of type Dep, but enforce that it is a Cloneable<T>. (Replace your orignial function by a simple function template that enforces this.) This guarantees that any Dep inside the master has a correctly implemented clone function.
Since Cloneable<MyType> has no public constructor, it cannot be inherited, however your actual MyType can be further inherited and used just as before.
Did TPTB outlaw all RTTI, or only dynamic_cast<>()? If you can use RTTI, then you can enforce the existence of the method as a postcondition of calling it:
#include <typeinfo>
#include <cassert>
#include <iostream>
#include <stdexcept>
class Base {
protected:
virtual Base* do_create() = 0;
virtual ~Base() {}
public:
Base* create() {
Base *that = this->do_create();
if( typeid(*this) != typeid(*that) ) {
throw(std::logic_error(std::string() +
"Type: " +
typeid(*this).name() +
" != " +
typeid(*that).name()));
}
return that;
}
};
class Derive1 : public Base {
protected:
Base* do_create() { return new Derive1(*this); }
};
class Derive2 : public Derive1 {};
void f(Base*p) { std::cout << typeid(*p).name() << "\n"; }
int main() {
Derive1 d1;
Base *pD1 = d1.create(); // will succeed with correct semantics
Derive2 d2;
Base *pD2 = d2.create(); // will throw exception due to missing Derive2::do_create()
}
If you control the base class AbstractDep then you can enforce that concrete leaf classes must be created by using a class template WithCloning. This leaf can then be sealed so that it cannot be inherited. Or more precisely, instances cannot be created of a derived class.
class AbstractDep
{
template< class Type > friend class WithCloning;
private:
enum FooFoo {};
virtual FooFoo toBeImplementedByLeafClass() = 0;
public:
virtual AbstractDep* clone() const = 0;
};
template< class Type > class WithCloning;
class Sealed
{
template< class Type > friend class WithCloning;
private:
Sealed() {}
};
template< class Type >
class WithCloning
: public Type
, public virtual Sealed
{
private:
AbstractDep::FooFoo toBeImplementedByLeafClass()
{
return AbstractDep::FooFoo();
}
public:
virtual WithCloning* clone() const
{
return new WithCloning( *this );
}
};
typedef WithCloning<AbstractDep> Dep;
class AbstractDerivedDep
: public AbstractDep
{
// AbstractDep::FooFoo toBeImplementedByLeafClass(); // !Not compile.
public:
};
typedef WithCloning<AbstractDerivedDep> DDep;
struct Foo: Dep {}; // !Does not compile if instantiated.
int main()
{
Dep d;
//Foo f;
}
If the classes require more than default construction then that most be solved additionally.
One solution is then to forward an argument pack from the WithCloning constructor (there is an example C++98 implementation on my blog, and C++0x supports that directly).
Summing up, to be instantiable the class must be WithCloning.
Cheers & hth.,
when you say that they are unknown, i presume they still inherit from a common base class /interface right?
only thing i can think of you can use to force is on the virtual base class add
virtual Base* clone() {
assert( 1==0 ); //needs to be overriden
}
so you are forced to override, but this is only detected at run-time when trying to call clone on a instance of a class that is missing the override
even if you are not allowed to use dynamic_cast or RTTI, you can still enable it for debug purposes locally on your build, if that will help you find the typeid of offending classes
it sounds like you are familiar with the clone pattern, but i'll post it quietly in here, and we can forget about it:
http://www.cplusplus.com/forum/articles/18757/