Reputation: 1259
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>>
{
};
Upvotes: 0
Views: 119
Reputation: 40836
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;
Upvotes: 2
Reputation: 217583
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>
{
};
Upvotes: 3