In curiously recurring template pattern I need to change nested type T of TDerivedClass<T> type. Is there a way to specify Base by not fully specified Derived1 class? Something like that: class Derived1 : public Base<T, Derived1<"NOT SPECIFIED TYPE SYNTAX">>, and then fully specify Derived1 but inside Base functions as TDerivedClass<int>. Or is there any other way to change T for this specific part of code?
template<typename T, typename TDerivedClass>
class Base
{
public:
void f()
{
std::vector<T> a;
TDerivedClass b;
TDerivedClass<int> c; // <- want to change T to arbitrary type (to int for example) without changing T
}
};
template<typename T>
class Derived1 : public Base<T, Derived1<T>>
{
};
template<typename T>
class Derived2 : public Base<T, Derived2<T>>
{
};
You probably want template template parameter:
template <typename T, template <typename> class TDerivedClass>
class Base
{
public:
void f()
{
std::vector<T> a;
TDerivedClass<T> b;
TDerivedClass<int> c;
}
};
template<typename T>
class Derived1 : public Base<T, Derived1>
{
};
template<typename T>
class Derived2 : public Base<T, Derived2>
{
};
You can pass the template class specifically:
template<typename T, template<typename> class TDerivedTemplate>
class Base
{
using TDerivedClass = TDerivedTemplate<T>;
public:
void f()
{
std::vector<T> a;
TDerivedClass b;
TDerivedTemplate<int> c;
}
};
template<typename T>
class Derived1 : public Base<T, Derived1> // Pass the template (Derived1) to instantiate new classes from
{
};
// Since you're changing the pattern anyways, you might as well
// have it detect the template from the type
template<typename TDerivedClass>
class Base;
template<template<typename> class TDerivedTemplate, typename T>
class Base<TDerivedTemplate<T>> {
using TDerivedClass = TDerivedTemplate<T>;
public:
void f() { /* Same as above */ }
}
template<typename T>
class Derived1 : public Base<Derived1<T>>
// Automatically gets the template. Also means it's harder to use Base<> wrong.
{
};
Or you can use a rebind type trait:
template<typename ToRebind, typename... NewTypes>
struct rebind;
template<template<typename...> class Template, typename... CurrentTypes, typename... NewTypes>
struct rebind<Template<CurrentTypes...>, NewTypes...> {
using type = Template<NewTypes...>;
}
// Used like
TDerivedClass b;
typename rebind<TDerivedClass, int>::type c;
Related
I am still working on this problem I posted some hours before:
[How to overload/specialize template class function to handle arithmetic types and a container-class
I tried to implement this solution. It compiles but the object is created with the DerivedClass-Constructor instead of the partial specialized template class DerivedClass< Eigen::ArrayBase >
Do you have an Idea where I made a (or some) misstakes?
template <typename T> class BaseClass
{
protected:
T mem;
public:
BaseClass(T arg) : mem(arg){};
};
template <typename T> class DerivedClass : public BaseClass<T>
{
public:
DerivedClass(T arg): BaseClass<T>(arg){};
};
template <typename T>
class DerivedClass<Eigen::ArrayBase<T> >
: public DerivedClass<Eigen::ArrayBase<T> >
{
public:
DerivedClass(Eigen::ArrayBase<T> arg):BaseClass<Eigen::ArrayBase<T> >(arg){};
};
int main
{
...
Eigen::Array3d arg = Array3d::Random(3);
DerivedClass<Eigen::Array3d> o(arg);
....
}
template<template<class...>class Z>
struct template_instance_test {
static std::false_type test(...);
template<class...Ts>
static std::true_type test( Z<Ts...> const* );
template<class X>
using tester = decltype(test( std::declval<X*>() ) );
};
template<template<class...>class Z, class T>
using is_derived_from_template = typename template_instance_test<Z>::template tester<T>;
we can now ask if something is an instance of a particular template, or derived from an instance of a particular template.
template<class X>
struct Base {};
template<class X>
struct Derived:Base<X> {};
template<class T>
struct Storage {
T data;
};
template<class T, class=void>
struct Instance:Storage<T> {
enum {is_special = false};
};
template<class T>
struct Instance<T, std::enable_if_t< is_derived_from_template<Base, T>{} > >:
Storage<T> {
enum { is_special = true };
};
int main() {
Instance<int> i; (void)i;
static_assert(!Instance<int>::is_special);
Instance<Derived<int>> j; (void)j;
static_assert(is_derived_from_template<Base, Base<int>>{});
static_assert(is_derived_from_template<Base, Derived<int>>{});
static_assert(Instance<Derived<int>>::is_special);
}
and we are done. Live example.
Your code should works if Eigen::Array3d is an alias (through using or typedef) of Eigen::ArrayBase<T> for some T.
But I suppose that Eigen::Array3d inherit from Eigen::ArrayBase<T>. So isn't a ``Eigen::ArrayBase`, so doesn't matches the partial specialization, so matches the main template.
If you want a specialization that intercept all classes derived from Eigen::ArrayBase, a possible solution is add an additional template parameter with a default value and activate the specialization only it T derive from some Eigen::ArrayBase.
Something as follows (caution: code not tested)
constexpr std::false_type isArray (...);
template <typename T>
constexpr std::true_type isArray (Eigen::ArrayBase<T> const *);
template <typename T, typename = std::true_type>
class DerivedClass : public BaseClass<T>
{
public:
DerivedClass(T arg): BaseClass<T>(arg){};
};
template <typename T>
class DerivedClass<T, decltype(isArray(std::declval<T*>())>
: public DerivedClass<T>
{
public:
DerivedClass (T arg) : BaseClass<T>(arg){};
};
I'm using the Visitor pattern to implement reflection without relying on RTTI.
My problem is:
I want to implement a Visitor which can cast different classes DerivedItem1, DerivedItem2, etc. derived from the same BaseItem class, to this BaseItem class.
The base class and one of the derived classes looks like this:
class BaseItem : public AbstractItem
{
virtual ~BaseItem(){}
virtual void visit(AbstractVisitor &v)
{
v.handle(*this);
}
}
class DerivedItem1 : public BaseItem
{
virtual ~DerivedItem(){}
virtual void visit(AbstractVisitor &v)
{
v.handle(*this);
}
}
The Visitor class:
class BaseVisitor : public AbstractVisitor
{
virtual ~BaseVisitor(){}
void handle(BaseItem &item)
{
// <-- stuff to do for all classes derived from BaseItem
}
}
It is not possible to implement the BaseVisitor like this,
since DerivedItem::visit(BaseVisitor) does not cast itself to its Base class
and BaseVisitor::handle(BaseItem &v) will never get called.
I want to implement the visitor as a template class, taking a base class and all derived classes as template parameters like this:
template <typename BaseT, typename... DerivedT>
class BaseVisitor : public AbstractVisitor
{
public:
virtual ~BaseVisitor(){}
// unpacking all DerivedT should happen here
// DerivedT_X are the packed template arguments ...DerivedT
void handle(DerivedT_1 &item)
{
// <-- cast item to BaseT, do stuff, return BaseT* to caller
}
void handle(DerivedT_2 &item)
{
// <-- cast item to BaseT, do stuff, return BaseT* to caller
}
};
Is it possible somehow with C++ to let the compiler generate this member functions on its own ?
You can't unpack the parameter pack across the body of the template definition as you were describing in the question, but you can use CRTP to assemble an class that inherits a hierarchy with templatized specializations for each of the type-parameters you supply:
#include <iostream>
template<class L, class... R> struct X;
template<class L>
struct X<L> { void handle(L& i) { std::cout << i.f() << "\n"; } };
template<class L, class... R>
struct X : public X<L>, public X<R...> { using X<L>::handle; using X<R...>::handle; };
struct A1 {
int f() { return 1; }
};
struct A2 {
int f() { return 2; }
};
struct B {
int f() { return 10; }
};
struct B1 : public B {
int f() { return 11; }
};
struct B2 : public B1 {
int f() { return 12; }
};
int main() {
X<A1, A2> x1;
A1 a1; A2 a2;
x1.handle(a1);
x1.handle(a2);
X<B, B1, B2> x2;
B b; B1 b1; B2 b2;
x2.handle(b);
x2.handle(b1);
x2.handle(b2);
}
With CRTP and variadic template, you may do something like:
// The generic visitor interface
template <typename ... Ts>
class IVisitor;
template <> class IVisitor<>
{
public:
virtual ~IVisitor() = default;
};
template <typename T> class IVisitor<T>
{
public:
virtual ~IVisitor() = default;
virtual void visit(const T&) = 0;
};
template <typename T, typename...Ts>
class IVisitor<T, Ts...> : IVisitor<T>, IVisitor<Ts...>
{
public:
using IVisitor<T>::visit;
using IVisitor<Ts...>::visit;
virtual ~IVisitor() = default;
};
// Helper for the concrete visitor using CRTP
template <typename Derived, typename Base, typename...Ts>
struct CRTPVisitorImpl;
template <typename Derived, typename Base>
struct CRTPVisitorImpl<Derived, Base> : Base {};
template <typename Derived, typename Base, typename T>
struct CRTPVisitorImpl<Derived, Base, T> : virtual Base
{
using Base::visit;
void visit(const T& t) override { static_cast<Derived&>(*this).doVisit(t); }
};
template <typename Derived, typename Base, typename T, typename ... Ts>
struct CRTPVisitorImpl<Derived, Base, T, Ts...> :
CRTPVisitorImpl<Derived, Base, T>,
CRTPVisitorImpl<Derived, Base, Ts...>
{
using CRTPVisitorImpl<Derived, Base, T>::visit;
using CRTPVisitorImpl<Derived, Base, Ts...>::visit;
};
// The generic Visitor
template <typename Derived, typename Base>
struct CRTPVisitor;
template <typename Derived, typename ... Ts>
struct CRTPVisitor<Derived, IVisitor<Ts...>> :
CRTPVisitorImpl<Derived, IVisitor<Ts...>, Ts...>
{};
// Helper to write visited
template <typename Derived, typename Base, typename Visitor>
struct Visited : Base
{
void accept(Visitor& visitor) const override {
visitor.visit(static_cast<const Derived&>(*this));
}
};
And usage:
struct ShapeVisitorPrinter : CRTPVisitor<ShapeVisitorPrinter, IShapeVisitor>
{
template <typename T>
void doVisit(T&& t) const {
t.print();
}
};
each Ivisitor::visit call doVisit with CRTP, so you just have to cover each case via template/overload/base class.
Demo
Suppose I have a class like so:
template<class T>
class Base{ };
Suppose I have another class like so:
template<class T, class Other>
class Derived :
public virtual Base<T>,
public virtual OtherRandomClass<Other>
{ };
Is there some way to create a template class to determine which version of Base (if any) a random class like Derived is derived from?
Here is a possible solution (working since C++11 - well, it works with C++14, but it does it with C++11 if you use Base<T> instead of auto as a return type for f):
#include<utility>
#include<type_traits>
template<class T>
class Base{ };
template<class T>
class OtherRandomClass{ };
template<class T, class Other>
class Derived :
public virtual Base<T>,
public virtual OtherRandomClass<Other>
{ };
template<typename T>
constexpr auto f(const Base<T> &b) { return b; }
template<typename T>
struct S {
using type = decltype(f(std::declval<T>()));
};
int main() {
static_assert(std::is_same<typename S<Derived<int, double>>::type, Base<int>>::value, "!");
}
It doesn't work if Derived inherits more than once from Base.
Using sfinae (something like the void_t idiom) one can even design a class that works similarly to enable_if: it has type only if T actually inherits from Base once.
It would have the following form:
template<typename T>
constexpr auto f(const Base<T> &b) { return b; }
template<typename...>
using void_t = void;
template<typename T, typename = void_t<>>
struct S { };
template<typename T>
struct S<T, void_t<decltype(f(std::declval<T>()))>> {
using type = decltype(f(std::declval<T>()));
};
This struct can be used at compile time for any template trickery you can imagine.
In both cases, S::type (if it exists) is the type of the base class from which Derived inherits, that is Base<T>.
See the static_assert in the main function of the example for further details.
#include <iostream>
#include <typeinfo>
// placeholder template
template<class SomeDerived> struct traits {};
template<class T>
class Base{ };
template<class T>
class OtherRandomClass{ };
template<class T, class Other>
class Derived :
public virtual Base<T>,
public virtual OtherRandomClass<Other>
{ };
// specialise for our class to provide introspection
template<
class T1,
class T2>
struct traits<
Derived<T1, T2>
>
{
using t1_type = T1;
using first_base_type = Base<T1>;
};
int main()
{
Derived<int, float> x;
using mytraits = traits<decltype(x)>;
std::cout << typeid(mytraits::t1_type).name() << std::endl;
std::cout << typeid(mytraits::first_base_type).name() << std::endl;
}
I have five classes, declared so:
template <typename T>
class A {
void fn(X);
};
template <typename T>
class B {};
class C {};
class D {};
class X {};
and I have two instances declared so:
A<B<C>> abc;
A<B<D>> abd;
How can I templatize fn so that one must call abc.fn() with an object of type C and abd.fn() with an object of type D?
You can do a partial specialization of your class like this:
template <typename T> class A;
template <typename T> class B {};
template <typename T>
class A<B<T> > {
public:
void fn(T) { }
};
class C {};
class D {};
int main(int,char**)
{
A<B<C>> abc;
A<B<D>> abd;
abc.fn(C());
abd.fn(D());
return 0;
}
If you want it to work for any template, and not just B, you can partially specialize class A like this:
template <typename T,template <typename> class U>
class A<U<T> > {
public:
void fn(T) { }
};
This is not going to be too pretty.
template <typename T>
class B {public: typedef T type;};
template <typename T>
class A {
void fn(typename T::type X);
//void fn(...){} // would prevent an error if T does not have type.
};
Basically you save the type in a typedef and then use that in A. This would error out of course if B does the T of A does not have T::type.
Consider the following:
template <typename T>
class Base {
public:
template <typename U>
class Nested { };
};
template <typename T>
class Derived : public Base<T> {
public:
//How do we typedef of redefine Base<T>::Nested?
using Base<T>::Nested; //This does not work
using Base<T>::template<typename U> Nested; //Cannot do this either
typedef typename Base<T>::template<typename U> Nested Nested; //Nope..
//now we want to use the Nested class here
template <typename U>
Class NestedDerived : public Nested { };
//or like this:
Nested<int> nestedVar; // obviously does not work
};
How to use the templated Nested class in the Derived class? Is this possible to do in current version of C++ standard?
Actually using works as advertised, it just doesn't get rid of the dependent-name issue in the template and it can't currently alias templates directly (will be fixed in C++0x):
template <class T>
struct Base {
template <class U> struct Nested {};
};
template <class T>
struct Derived : Base<T> {
using Base<T>::Nested;
// need to prefix Nested with template because
// it is a dependent template:
struct X : Base<T>::template Nested<int> {};
// same here:
template<class U>
struct Y : Base<T>::template Nested<U> {};
// data member, typename is needed here:
typename Base<T>::template Nested<int> data;
};
void f() {
Derived<int>::Nested<int> n; // works fine outside
}
There is another possible gotcha when using Derived<T>::Nested in templates, but again that is a dependent-name issue, not inheritance-related:
template<class T>
void g() {
// Nested is a dependent type and a dependent template, thus
// we need 'typename' and 'template':
typedef typename Derived<T>::template Nested<int> NestedInt;
}
Just remember that names that depend on template arguments have to be
prefixed with typename if its a dependent type: typename A<T>::B
directly prefixed with template if its a dependent template: A<T>::template f<int>()
both if both: typename A<T>::template B<int>
typename is illegal in base-class-lists: template<class T> struct A : B<T>, C<T>::template D<int> {};
This seems to work:
(EDIT: added some more lines to show the first template statement. And thanks to Samir Talwar for correcting my formatting!)
template <typename T, typename U>
class Derived : public Base<T> {
public:
typedef typename Base<T>::template Nested<U> Nested;
class NestedDerived : public Nested { };
Nested nestedVar;
};
Try this:
template <typename T>
class Base {
public:
template <typename U>
class Nested { };
};
template <typename T>
class Derived : public Base<T> {
public:
//How do we typedef of redefine Base<T>::Nested?
//using Base<T>::Nested; //This does not work
//using Base<T>::template<typename U> Nested; //Cannot do this either
//typedef typename Base<T>::template<typename U> Nested Nested; //Nope..
//now we want to use the Nested class here
template <typename U>
class NestedDerived : public Base<T>::template Nested<U> { };
};
int main()
{
Base<int>::Nested<double> nested;
Derived<int>::NestedDerived<double> nested_derived;
return 0;
}
Compiled fine using gcc 4.3.3 on slackware 13
I'm still not 100% sure what you want, but you could try.
This compiled on Visual Studio
template <typename T>
class Base {
public:
template <typename U>
class Nested { };
};
template <typename T>
class Derived : public Base<T> {
public:
//now we want to use the Nested class here
template <typename U>
class NestedDerived : public Nested<U> { };
};
int _tmain(int argc, _TCHAR* argv[])
{
Base<int>::Nested<double> blah2;
Derived<int>::NestedDerived<int> blah;
return 0;
}