Is it possible to have multiple template types in C++?
For example;
template<template<typename> class BaseClass>
class MyClass {};
template<class BaseClass>
class MyClass {};
And using it;
// Using the first template (template<typename> class BaseClass)
template<typename SubClass>
class MyFirstSubClass : public MyClass<MyFirstSubClass> {};
// Using the second template (class BaseClass)
class MySecondSubClass : public MyClass<MySecondSubClass> {};
You can't have separate templates with the same name, but you can have a base template and one or more specializations of that class.
template<class BaseClass>
class MyClass
{ };
template<class T, template<typename> class BaseClass>
class MyClass<BaseClass<T>>
{ };
template<>
class MyClass<int>
{ };
No, it's not possible. You'll have to have two different template classes:
template<template<typename> class BaseClass>
class MyClassA {};
template<class BaseClass>
class MyClassB {};
Related
I'm trying to check if a class that I'm templating is inheriting from another templated class, but I can't find the correct way to do it.
Right now I have the following:
#include <iostream>
template <typename MemberType, typename InterfaceType>
class Combination : public InterfaceType
{
public:
Combination();
virtual ~Combination();
private:
MemberType* pointer;
};
class MyInterface {};
class MyMember {};
class MyCombination : public Combination<MyMember, MyInterface>
{
};
int main()
{
static_assert(std::is_base_of_v<Combination<MyMember, MyInterface>, MyCombination>);
std::cout << "hello";
}
Which is working fine, but in the place this template is placed, I don't have access to the template parameters definitions, and this should be quite generic. What I'd like is to test for the MyCombination class to inherit from a generic Combination without taking into account the template arguments, something like this:
static_assert(std::is_base_of_v<Combination, MyCombination>);
or
static_assert(std::is_base_of_v<Combination<whatever, whatever>, MyCombination>);
Would you know how to check for this?
In this case I can't use boost libraries or other external libraries.
Thanks!
EDIT: I don't have access to modify the Combination class, and what I can change is the assert and the My* classes.
This can easily be done with the C++20 concepts. Note that it requires a derived class to have exactly one public instantiated base class.
template <typename, typename InterfaceType>
class Combination : public InterfaceType {};
class MyInterface {};
class MyMember {};
class MyCombination : public Combination<MyMember, MyInterface> {};
template<class Derived, template<class...> class Base>
concept derived_from_template = requires (Derived& d) {
[]<typename... Ts>(Base<Ts...>&) {}(d);
};
static_assert(derived_from_template<MyCombination, Combination>);
Demo
The equivalent C++17 alternative would be
#include <type_traits>
template<template<class...> class Base, typename... Ts>
void test(Base<Ts...>&);
template<template<class...> class, class, class = void>
constexpr bool is_template_base_of = false;
template<template<class...> class Base, class Derived>
constexpr bool is_template_base_of<Base, Derived,
std::void_t<decltype(test<Base>(std::declval<Derived&>()))>> = true;
static_assert(is_template_base_of<Combination, MyCombination>);
I have some template class
template <typename T> class Base { };
I trying to inherit Derived class from Base and use Internal class that is nested of Derived as a generic argument of Base.
class Derived : Base<Internal> {
public: class Internal { };
}
But compiler doesn't see Internal in Base.
Is it possible to solve my problem with keeping Internal class as nested of Derived?
And if it is possible - How?
You can! Nope
(similar question)
I don't think that this can work. In order to define the class Derived you need to know the base class ("it must be a complete type") first; to instantiate the template Base into a class you need to have a type. Inner however is only a type "inside" of Derived; it's part of it's definition.
Definition of Derived ---needs---> Base<Derived::Inner>
^ |
|----------needs----------------|
Even an indirection does not help:
template<typename T>
class Base {};
template<template<class> class X, typename T>
struct UseInner : public X<typename T::Inner> {};
class Derived : UseInner<Base, Derived>
{
public: class Inner {};
};
In contrast to this, the CRTP works because there the template parameter can be an incomplete type ("no need to access internals").
Wrapping in a template doesn't work:
template<typename T>
class Base {};
template<template<class>class X>
struct Wrap
{
struct Derived : X<typename Derived::Inner> {
struct Inner {};
};
};
using RealDerived = typename Wrap<Base>::Derived;
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;
Lets say I have an template class and i would like to derive it from an abstract class
I wrote the abstract class declaration as follows:
template<typename T, class Derived>
class AbstractClass{
};
How do I derive my template class correctly?
At the moment it looks like:
template <typename T>
class TemplateClass{};
I see you are playing with CRTP? The proper way is following:
template <typename T>
class TemplateClass : public AbstractClass<T, TemplateClass<T> > {};
I have a templated base class which follows:
template<class scalar_type, template<typename > class functor>
class convex_opt{ ..
};
How to derive a class from this templated class?
template<class scalar_type, template<typename > class functor>
class derived : public convex_opt<scalar_type, functor> {
...
?