I'm trying to implement a kind of CRTP (if I well understand what it is) with multiple inheritance.
My main goal is to have a unified way to access list of instances of each subclass.
May problem seems to reside in the namespace utilization.
Here is the code of the simplest version :
http://ideone.com/rFab5
My real problem is more similar to :
http://ideone.com/U7cAf
I have an additional warning using clang++ :
test.cpp:28:63: warning: static data member specialization of 'instances' must originally be declared in namespace 'NS1'; accepted as a C++0x extension [-Wc++0x-extensions]
template <> std::list<NS1::Derived*> NS1::Base<NS1::Derived>::instances;
^
test.cpp:15:34: note: explicitly specialized declaration is here
static std::list<T*> instances;
Problem has been updated since it does not behave the same using namespaces.
Problem re-edited to post code on Ideone
The problem is that you've tried to define the list variable wrong. You need to provide a definition for Base, in general- you don't just define it for the one part that happens to be Derived's subclass, unless it's an explicit specialization.
template<typename T> std::list<T*> NS1::Base<T>::instances;
http://ideone.com/Vclac
Compiles with no errors. There are no intermediates or anything like that required.
Changing Base() and Intermediary() to Base<U>() and Intermediary<Derived> in the constructors makes the code OK for GCC.
There is no reason to change the definition of instances in the second case: the template is identical as the first situation.
Afaik, you got the following options.
First, if Intermediate is always templated on the derived type, you don't need a list for it, because it will never be the most derived type. If it could be templated on other types / not be derived, you can add a defaulted non-type bool template parameter like so:
template<bool, class A, class B>
struct select_base{
typedef A type;
};
template<class A, class B>
struct select_base<false,A,B>{
typedef B type;
};
template<class T, bool IsDerived = false>
class Intermediate
: public select_base<IsDerived,
Base<T>,
Base<Intermediate<T> >
>::type
{
// ...
};
// derived use
class Derived : public Intermediate<Derived, true>
{
// ...
};
// non-derived use:
Intermediate<int> im;
If the intermediate class is not templated and does not already derive from Base, you need to derive from Base again in the most derived class:
class Derived : public Intermediate, public Base<Derived>
{
// ...
};
The big problem comes when the intermediate also derives from Base but is not templated. You can add a defaulted derived type, but that would make the non-derived use a bit more ugly:
#include <type_traits> // C++0x, use std::
//#include <tr1/type_traits> // C++03, use std::tr1::
struct nil_base{};
template<class Derived = nil_base>
class Intermediate
: public select_base<std::is_same<Derived,nil_base>::value,
Base<Intermediate<Derived> >, //
Base<Derived>
>::type
{
// ...
};
// derived use now without boolean flag
class Derived : public Intermediate<Derived>
{
// ...
};
// non-derived use a bit uglier
Intermediate<> im;
// ^^ -- sadly needed
The following compiles OK with MinGW g++ 4.4.1, MSVC 10.0, and Comeau Online 4.3.10.1:
#include <list>
template <class T>
class Base
{
protected:
Base()
{
instances.push_back(static_cast<T*>(this));
}
private:
static std::list<T*> instances;
};
template <class U>
class Intermediary : public Base<U>
{
protected:
Intermediary()
:Base<U>()
{
}
};
class Derived : public Intermediary<Derived>
{
public:
Derived()
:Intermediary<Derived>()
{
}
};
template<class Derived> std::list<Derived*> Base<Derived>::instances;
int main()
{}
The instances definition is copied verbatim from your question.
I say as Isaac Newton, I frame no hypotheses!
Cheers & hth.,
Related
Often in derived template classes I need to refer to the base to access members. I end up writing code like this:
template<typename A>
struct BaseClass
{
};
template<typename B>
struct Derived : public BaseClass<int>
{
using Base = BaseClass<int>;
};
This gets more verbose and harder to maintain for a large number of classes with a lot of template arguments.
Is there a cleaner way to import base symbols in this case?
I think you can do things the other way i.e. defer the base resolution to the base class instead, so that it would be automatically resolved for any new derived class without bothering of rewriting it for each one.
Something like:
template <typename A>
struct BaseClass
{
using Base = BaseClass<A>;
};
template <typename B>
struct Derived : public BaseClass<int>
{};
Live example
If Derived is not itself a template class: You can simply use BaseClass (the inherited injected-class-name):
struct Derived : public BaseClass<int>
{
void f()
{
BaseClass::f();
}
};
If it is also a template, using Base = BaseClass<int>; is probably the best way.
I'm trying to implement a derived class inheriting from a base template, with the derived class as its template parameter (the example below hopefully clears things up):
template <class T>
struct S
{
T f() {return T();}
};
struct D : public S<D>
{
};
This compiles and works well on gcc, clang, and msvc as well. Now, I want to "make sure" that the template parameter inherits from the base class:
#include <concepts>
template <class T>
concept C
= requires ( T t )
{
{ t.f() };
};
template <C T>
struct S
{
T f() {return T();}
};
struct D : public S<D>
{
};
However, this gets rejected by every compiler, with clang providing the most insight:
error: constraints not satisfied for class template 'S' [with T = D]
struct D : public S<D>
^~~~
note: because 'D' does not satisfy 'C'
template <C T>
^
note: because 't.f()' would be invalid: member access into incomplete type 'D'
{ t.f() };
I understand where the compiler is coming from: D is not fully defined yet when the constraint has to be checked, so it fails in lieu of the necessary information. That said, I'm kinda disappointed that no attempt is made to complete the definition of the derived class before evaluating a yet uncheckable constraint.
Is this behaviour intended? Is there another way to check the inheritance that actually works?
By the way, gcc gives a rather useless error message in this case.
You can check the requirement in the default constructor of the base class
#include <type_traits>
template<class Derived>
class Base
{
public:
Base()
{
static_assert(std::is_base_of_v<Base<Derived>, Derived>);
}
};
class Derived : public Base<Derived>
{ };
This must also be checked in any other user defined non-copy and non-move constructors of base. This is valid as Derived is fully defined when the constructor is instantiated.
I have some code like this
class A : public b<T>
{
public:
typedef b<T> _baseclass; // why we need this declaration
};
What is the use of typedef inside the class?
Is the definition limited to this class only?
Shall we create this as static and use without crating an object of the class?
This member type will be available outside of the class definition too, which is convenient in template code. If you passed an A into a function template, or maybe some other classes that also have _baseclass member types, then you can use _baseclass to find out what the base is without needing to know exactly what the top-level type is.
Standard templates like std::vector and std::map have member types like value_type — these do not signify a base class but have a similar purpose, in that you can use value_type anywhere a container is used, no matter which container is used.
Swapping typedef to using (because I want to), here's an example:
// The class templates
template <typename T>
struct Base {};
struct A : Base<int>
{
using base_class = Base<int>;
};
struct B : Base<char>
{
using base_class = Base<char>;
};
struct C : Base<bool>
{
using base_class = Base<bool>;
};
// The example
template <typename T>
void foo()
{
// typename needed because base_class is a "dependent name"
// (just go with it)
typename T::base_class the_base;
// This line is to suppress "unused variable" warnings
(void)the_base;
}
int main()
{
foo<A>();
foo<B>();
foo<C>();
}
Though this particular program doesn't actually "do anything", it shows a function template foo that can "know" what the base class was in each case, without any further information about exactly what T is. And it'll work for any class to which you've added a base_class member type!
I was wondering how we can declare an interface in C++ without using virtual functions. After some internet searching I put together this solution:
#include <type_traits>
using namespace std;
// Definition of a type trait to check if a class defines a member function "bool foo(bool)"
template<typename T, typename = void>
struct has_foo : false_type { };
template<typename T>
struct has_foo<T, typename enable_if<is_same<bool, decltype(std::declval<T>().foo(bool()))>::value, void>::type> : true_type { };
// Definition of a type trait to check if a class defines a member function "void bar()"
template<typename T, typename = void>
struct has_bar : false_type { };
template<typename T>
struct has_bar<T, typename enable_if<is_same<void, decltype(std::declval<T>().bar())>::value, void>::type> : true_type { };
// Class defining the interface
template <typename T>
class Interface{
public:
Interface(){
static_assert(has_foo<T>::value == true, "member function foo not implemented");
static_assert(has_bar<T>::value == true, "member function bar not implemented");
}
};
// Interface implementation
class Implementation:Interface<Implementation>{
public:
// If the following member functions are not declared a compilation error is returned by the compiler
bool foo(bool in){return !in;}
void bar(){}
};
int main(){}
I'm planning to use this design strategy in a project where I will use static polymorphism only.
The C++ standard I will use in the project is C++11.
What do you think are the pros and cons of this approach?
What improvements can be made on the code I proposed?
EDIT 1:
I just realised that inheriting from Interface is not needed. This code could also be used:
class Implementation{
Interface<Implementation> unused;
public:
bool foo(bool in){return !in;}
void bar(){}
};
EDIT 2-3:
One major difference between the static_assert solution (with or without CRTP) and the standard CRTP is that the CRTP does not guarantee that the derived class implements all the interface members. E.g., the following code compiles correctly:
#include <type_traits>
using namespace std;
template< typename T>
class Interface{
public:
bool foo(bool in){
return static_cast<T*>(this)->foo(in);
}
void bar(){
static_cast<T*>(this)->bar();
}
};
class Implementation: public Interface<Implementation>{
public:
// bool foo(bool in){return !in;}
// void bar(){}
};
int main(){}
An error about a missing member function will be returned by the compiler only when the functions foo or bar will be required.
The way I see it, the static_assert solution feels more like an interface declaration than CRTP alone.
An common way to implement static polymorphism is to use CRTP.
With this pattern, you define an templated interface class, whose methods forward to the template:
// Interface
template <typename T>
struct base {
void foo(int arg) {
static_cast<T*>(this)->do_foo(arg);
}
};
You implementation the inherits from the base class and implements the methods:
// Implementation
struct derived : base<derived> {
void do_foo(int arg) {
std::cout << arg << '\n'
}
};
This pattern has the advantage that it looks "feels" a lot like regular runtime polymorphism, and the error messages are generally quite sane. Because all the code is visible to the compiler, everything can be inlined so there's no overhead.
It appears that you want to implement concepts (lite). You may want to read the article before attempting an implementation.
Absent compiler support, you can partially implement this idea. Your static_assert idea is a known way to express interface requirements.
Consider the Sortable example from the link. You can create a class template Sortable, use static_assert to assert all kind of thinks about the template parameter. You explain to your users that they need to implement a certain cet of methods, and to enforce that set is implemented, they need to make use of Sortable<TheirClass> one way or another.
In order to express, right in a function declaration. the idea that your function requires a Sortable, you will have to resort to something like this:
template <typename Container>
auto doSomethingWithSortable (Container&) -> std::enable_if<Implements<Container, Sortable>>::type;
In the CRTP pattern, we run into problems if we want to keep the implementation function in the derived class as protected. We must either declare the base class as a friend of the derived class or use something like this (I have not tried the method on the linked article). Is there some other (simple) way that allows keeping the implementation function in the derived class as protected?
Edit: Here is a simple code example:
template<class D>
class C {
public:
void base_foo()
{
static_cast<D*>(this)->foo();
}
};
class D: public C<D> {
protected: //ERROR!
void foo() {
}
};
int main() {
D d;
d.base_foo();
return 0;
}
The above code gives error: ‘void D::foo()’ is protected with g++ 4.5.1 but compiles if protected is replaced by public.
It's not a problem at all and is solved with one line in derived class:
friend class Base< Derived >;
#include <iostream>
template< typename PDerived >
class TBase
{
public:
void Foo( void )
{
static_cast< PDerived* > ( this )->Bar();
}
};
class TDerived : public TBase< TDerived >
{
friend class TBase< TDerived > ;
protected:
void Bar( void )
{
std::cout << "in Bar" << std::endl;
}
};
int main( void )
{
TDerived lD;
lD.Foo();
return ( 0 );
}
As lapk recommended, problem can be solved with simple friend class declaration:
class D: public C<D> {
friend class C<D>; // friend class declaration
protected:
void foo() {
}
};
However, that exposes all protected/private members of derived class and requires custom code for each derived class declaration.
The following solution is based on the linked article:
template<class D>
class C {
public:
void base_foo() { Accessor::base_foo(derived()); }
int base_bar() { return Accessor::base_bar(derived()); }
private:
D& derived() { return *(D*)this; }
// accessor functions for protected functions in derived class
struct Accessor : D
{
static void base_foo(D& derived) {
void (D::*fn)() = &Accessor::foo;
(derived.*fn)();
}
static int base_bar(D& derived) {
int (D::*fn)() = &Accessor::bar;
return (derived.*fn)();
}
};
};
class D : public C<D> {
protected: // Success!
void foo() {}
int bar() { return 42; }
};
int main(int argc, char *argv[])
{
D d;
d.base_foo();
int n = d.base_bar();
return 0;
}
PS: If you don't trust your compiler to optimize away the references, you can replace the derived() function with the following #define (resulted in 20% fewer lines of disassembly code using MSVC 2013):
int base_bar() { return Accessor::base_bar(_instance_ref); }
private:
#define _instance_ref *static_cast<D*>(this) //D& derived() { return *(D*)this; }
After some I came with a solution that works event for private members of templated derived classes. It does not solves the problem of not exposing all the members of the derived class to the base, since it uses a friend declaration on the whole class. On the other hand, for the simple case, this does not requires repeating the base name, nor it's template parameters and will always work.
First the simple case when the derived is non-template. The base takes an additional void template parameter just to show that everything still works in the case of extra template parameters of the base. The only needed one, as per the CRTP, is the typename Derived.
//Templated variadic base
template <typename Derived, typename...>
struct Interface
{
using CRTP = Interface; //Magic!
void f() { static_cast<Derived*>(this)->f(); }
};
//Simple usage of the base with extra types
//This can only be used when the derived is NON templated
class A : public Interface<A, void>
{
friend CRTP;
void f() {}
};
The only thing needed for this to work is the using CRTP = Interface; declaration in the base and the friend CRTP; declaration in the derived.
For the case when the derived is itself templated the situation is trickier. It took me some time to come to the solution, and I'm sure it's still not perfect.
Most of the magic happens inside these templates:
namespace CRTP
{
template <template <typename, typename...> class _Base, typename _Derived, typename... _BaseArgs>
struct Friend { using Base = _Base<_Derived, _BaseArgs...>; };
template <template <typename, typename...> class _Base, typename ..._BaseArgs>
struct Base
{
template <template <typename...> class _Derived, typename... _DerivedArgs>
struct Derived : public _Base<_Derived<_DerivedArgs...>, _BaseArgs...> {};
};
}
Their usage is more or less straightforward. Two use the above templates several steps are needed.
First, when inheriting in the derived class the inherited-from base class, and it's optional parameters, needs to be given. This is done using CRTP::Base<MyBase, BaseOptional....>, where MyBase is the name of the class used for CRTP, and the BaseOptional... are template parameters that are passed to the base class as-is, directly after passing our derived class that is supplied in the next step. When the base class does not accepts any additional template parameters they can be omitted completely: CRTP::Base<MyBase>.
The next step is to introduce the derived class (the whole point of CRTP). This is done by following the above CRTP::Base<...> with a ::Derived<ThisDerived, DerivedOptional...>. Where ThisDerived is the class this is defined in, and DerivedOptional... are all the template parameters declared in this class'es template declaration. The optional parameters much be specified exactly as they appear in the class template declaration.
The last step is declaring the base class as a friend. This is done by declaring friend typename CRTP::Friend<MyBase, ThisDerived, BaseOptional...>::Base somewhere in the class. The BaseOptional... template perameters must be repeated exactly as they appear in the CRTP::Base<MyBase, BaseOptional...> that is inherited from.
Follows is an example of using a templated derived when the base does not depends on the templated types (but it still can take other template parameters, void in this example).
//Templated derived with extra, non-dependant types, passed to the base
//The arguments passed to CRTP::Base::Derived<, ARGS> must exactly match
// the template
template <typename T, typename... Args>
class B : public CRTP::Base<Interface, void>::Derived<B, T, Args...>
{
friend typename CRTP::Friend<Interface, B, void>::Base;
void f() {}
};
Next is an example for when the base depends on template parameters of the derived. The only difference from the previous example is the template keyword. An experiment shows that if the keyword is specified for the previous, non dependant, case the code also complies cleanly.
//Templated derived with extra dependant types passed to the base
//Notice the addition of the "template" keyword
template <typename... Args>
class C : public CRTP::Base<Interface, Args...>::template Derived<C, Args...>
{
friend typename CRTP::Friend<Interface, C, Args...>::Base;
void f() {}
};
Please note that these templates do not work for non-templated derived classes. I will update this answer when I find the solution, so a unified syntax could be used for all cases. The closest thing that can be done is just using some fake template parameter. Note that it still must be named and passed to the CRTP machinery. For example:
template <typename Fake = void>
class D : public CRTP::Base<Interface>::Derived<D, Fake>
{
friend typename CRTP::Friend<Interface, D>::Base;
void f() {}
};
Note that A, B, C & D are declared as class. That is, all their members are private.
Follows is some code that uses the above classes.
template <typename... Args>
void invoke(Interface<Args...> & base)
{
base.f();
}
int main(int, char *[])
{
{
A derived;
//Direct invocation through cast to base (derived.f() is private)
static_cast<A::CRTP &>(derived).f();
//Invocation through template function accepting the base
invoke(derived);
}
{
B<int> derived;
static_cast<B<int>::CRTP &>(derived).f();
invoke(derived);
}
{
C<void> derived;
static_cast<C<void>::CRTP &>(derived).f();
invoke(derived);
}
{
D<void> derived;
static_cast<D<>::CRTP &>(derived).f();
invoke(derived);
}
return 0;
}
The invoke free-standing templated function works for any class derived from the base.
Also shown is how to cast the derived to the base without the need to actually specify the name of the base.
Surprisingly, this does not depend on any system headers.
The full code is available here: https://gist.github.com/equilibr/b27524468a0519aad37abc060cb8bc2b
Comments and corrections are welcome.