Template template parameters with variadic templates - c++

For the sake of clarity, I've removed things like the constructor & destructor etc from the below where they don't add anything to the question. I have a base class that is used to create a common ancestor for a derived template class.
class PeripheralSystemBase {
public:
virtual void someFunctionThatsCommonToAllPeripherals() {}
};
template <class T, uint32_t numPeripherals = 1>
class PeripheralSystem : public PeripheralSystemBase {
public:
PeripheralSystem() : vec(T) {}
std::vector<T> vec; // different types of T is the reason why I need to template this class
};
// A & B declaration & definition are irrelevant here
class A{};
class B{};
// There are multiple different derived variants of PeripheralSystem
// At the moment, each has different template parameters
template <uint32_t customisableParam1>
class DerivedSystem1 : public PeripheralSystem<A, 1> {
public:
DerivedSystem1() : PeripheralSystem<A, 1>() {}
};
template <uint32_t customisableParam1, uint8_t customisableParam2>
class DerivedSystem2 : public PeripheralSystem<B, 1> {
public:
DerivedSystem2() : PeripheralSystem<B, 1>() {/*maybe use customisableParam2 here */}
};
So now I have 2 templates classes, each derived from the same ancestor class, one containing a vector containing type A, the other of type B; each has different template parameters. So far, so good.
Now for the question. I would like to be able to create a container template to contain none, one or more of the derived versions of PeripheralSystem inside it and I think I may be able to use variadic templates to do this, but I've got a bit stuck on the syntax over the past day or so. At compile time, I'd like to be able to create an instance of the container class. Perhaps something like:
template< template<typename ...> class args...>
class ContainerClass {
public:
ContainerClass() : container({args}) {}
std::vector<PeripheralSystem> container;
};
// possible usage
ContainerClass<DerivedSystem1<1>> cc1;
ContainerClass<DerivedSystem2<2, 3>> cc2;
ContainerClass<DerivedSystem1<1>, DerivedSystem2<2, 3>> cc3;
I know the variadic format I'm using isn't right, as I get:
error: expected ',' or '>' in template-parameter-list template<
template class args ...> >
What I'm trying to tell the compiler is that I want to supply a variable number of template-type parameters to the template, each of which has a variable number of template parameters. Am I able to do this with variadic templates please? Any suggestions on the correct syntax please?

You've got your ellipsis in the wrong place. Try:
template<template<typename...> class... Args>
^^^ here
However, you don't actually want template template parameters; since DerivedSystem1<1> is a type, not a template, you just want ordinary typename parameters:
template<typename... Args>
class ContainerClass {
For the actual container, you can't use vector<PeripheralSystem> as that is homogeneous and will slice the derived types down to PeripheralSystem. If you add a virtual destructor to PeripheralSystem you can use vector<unique_ptr<PeripheralSystem>>:
template<typename... Args>
class ContainerClass {
public:
ContainerClass() : container{std::make_unique<Args>()...} {}
std::vector<std::unique_ptr<PeripheralSystem>> container;
};
However, tuple would work just as well and result in fewer allocations:
template<typename... Args>
class ContainerClass {
public:
ContainerClass() : container{Args{}...} {}
std::tuple<Args...> container;
};

Related

C++ using declaration for parameter pack

I would like to define a class which inherits from a bunch of classes but which does not hide some specific methods from those classes.
Imagine the following code:
template<typename... Bases>
class SomeClass : public Bases...
{
public:
using Bases::DoSomething...;
void DoSomething(){
//this is just another overload
}
};
The problem is now if just one class does not have a member with the name DoSomething I get an error.
What I already tried was emulating an "ignore-if-not-defined-using" with a macro and SFINAE but to handle all cases this becomes very big and ugly!
Do you have any idea to solve this?
It would be really nice if I could define: "Hey using - ignore missing members".
Here I have some sample code: Godbolt
The problem with Jarod42's approach is that you change what overload resolution looks like - once you make everything a template, then everything is an exact match and you can no longer differentiate between multiple viable candidates:
struct A { void DoSomething(int); };
struct B { void DoSomething(double); };
SomeClass<A, B>().DoSomething(42); // error ambiguous
The only way to preserve overload resolution is to use inheritance.
The key there is to finish what ecatmur started. But what does HasDoSomething look like? The approach in the link only works if there is a single, non-overloaded, non-template. But we can do better. We can use the same mechanism to detect if DoSomething exists that is the one that requires the using to begin with: names from different scopes don't overload.
So, we introduce a new base class which has a DoSomething that will never be for real chosen - and we do that by making our own explicit tag type that we're the only ones that will ever construct. For lack of a better name, I'll name it after my dog, who is a Westie:
struct westie_tag { explicit westie_tag() = default; };
inline constexpr westie_tag westie{};
template <typename T> struct Fallback { void DoSomething(westie_tag, ...); };
And make it variadic for good measure, just to make it least. But doesn't really matter. Now, if we introduce a new type, like:
template <typename T> struct Hybrid : Fallback<T>, T { };
Then we can invoke DoSomething() on the hybrid precisely when T does not have a DoSomething overload - of any kind. That's:
template <typename T, typename=void>
struct HasDoSomething : std::true_type { };
template <typename T>
struct HasDoSomething<T, std::void_t<decltype(std::declval<Hybrid<T>>().DoSomething(westie))>>
: std::false_type
{ };
Note that usually in these traits, the primary is false and the specialization is true - that's reversed here. The key difference between this answer and ecatmur's is that the fallback's overload must still be invocable somehow - and use that ability to check it - it's just that it's not going to be actually invocable for any type the user will actually use.
Checking this way allows us to correctly detect that:
struct C {
void DoSomething(int);
void DoSomething(int, int);
};
does indeed satisfy HasDoSomething.
And then we use the same method that ecatmur showed:
template <typename T>
using pick_base = std::conditional_t<
HasDoSomething<T>::value,
T,
Fallback<T>>;
template<typename... Bases>
class SomeClass : public Fallback<Bases>..., public Bases...
{
public:
using pick_base<Bases>::DoSomething...;
void DoSomething();
};
And this works regardless of what all the Bases's DoSomething overloads look like, and correctly performs overload resolution in the first case I mentioned.
Demo
How about conditionally using a fallback?
Create non-callable implementations of each method:
template<class>
struct Fallback {
template<class..., class> void DoSomething();
};
Inherit from Fallback once for each base class:
class SomeClass : private Fallback<Bases>..., public Bases...
Then pull in each method conditionally either from the base class or its respective fallback:
using std::conditional_t<HasDoSomething<Bases>::value, Bases, Fallback<Bases>>::DoSomething...;
Example.
You might add wrapper which handles basic cases by forwarding instead of using:
template <typename T>
struct Wrapper : T
{
template <typename ... Ts, typename Base = T>
auto DoSomething(Ts&&... args) const
-> decltype(Base::DoSomething(std::forward<Ts>(args)...))
{
return Base::DoSomething(std::forward<Ts>(args)...);
}
template <typename ... Ts, typename Base = T>
auto DoSomething(Ts&&... args)
-> decltype(Base::DoSomething(std::forward<Ts>(args)...))
{
return Base::DoSomething(std::forward<Ts>(args)...);
}
// You might fix missing noexcept specification
// You might add missing combination volatile/reference/C-elipsis version.
// And also special template versions with non deducible template parameter...
};
template <typename... Bases>
class SomeClass : public Wrapper<Bases>...
{
public:
using Wrapper<Bases>::DoSomething...; // All wrappers have those methods,
// even if SFINAEd
void DoSomething(){ /*..*/ }
};
Demo
As Barry noted, there are other drawbacks as overload resolution has changed, making some call ambiguous...
Note: I proposed that solution as I didn't know how to create a correct traits to detect DoSomething presence in all cases (overloads are mainly the problem).
Barry solved that, so you have better alternative.
You can implement this without extra base classes so long as you’re willing to use an alias template to name your class. The trick is to separate the template arguments into two packs based on a predicate:
#include<type_traits>
template<class,class> struct cons; // not defined
template<class ...TT> struct pack; // not defined
namespace detail {
template<template<class> class,class,class,class>
struct sift;
template<template<class> class P,class ...TT,class ...FF>
struct sift<P,pack<>,pack<TT...>,pack<FF...>>
{using type=cons<pack<TT...>,pack<FF...>>;};
template<template<class> class P,class I,class ...II,
class ...TT,class ...FF>
struct sift<P,pack<I,II...>,pack<TT...>,pack<FF...>> :
sift<P,pack<II...>,
std::conditional_t<P<I>::value,pack<TT...,I>,pack<TT...>>,
std::conditional_t<P<I>::value,pack<FF...>,pack<FF...,I>>> {};
template<class,class=void> struct has_something : std::false_type {};
template<class T>
struct has_something<T,decltype(void(&T::DoSomething))> :
std::true_type {};
}
template<template<class> class P,class ...TT>
using sift_t=typename detail::sift<P,pack<TT...>,pack<>,pack<>>::type;
Then decompose the result and inherit from the individual classes:
template<class> struct C;
template<class ...MM,class ...OO> // have Method, Others
struct C<cons<pack<MM...>,pack<OO...>>> : MM...,OO... {
using MM::DoSomething...;
void DoSomething();
};
template<class T> using has_something=detail::has_something<T>;
template<class ...TT> using C_for=C<sift_t<has_something,TT...>>;
Note that the has_something here supports only non-overloaded methods (per base class) for simplicity; see Barry’s answer for the generalization of that.

Specializing Template Classes with Parameter Packs

I'm using inheritance with a set of classes. One of the child classes takes in an std::function(ReturnTy<ParamTypes...>), along with the ParamTypes arguments. The class signature and constructor look like:
template<class ReturnTy, class... ParamTypes>
class Child : public Interface
{
public:
Child(ReturnTy default_value, ParamTypes... args)
: func_set_(false)
, m_Args(std::make_tuple(std::forward<ParamTypes>(args)...))
, m_ReturnValue(default_value)
{}
private:
bool func_set_;
std::function<ReturnTy(ParamTypes...)> m_Funciton;
std::tuple<ParamTypes...> m_Args;
ReturnTy m_ReturnValue;
};
My issue is when I want to specialize for the case where there are no parameters. Furthermore, I also want to specialize for the case which ReturnTy=void and there are parameters. I found an answer that is close to what I'm looking for here, but it doesn't exactly cover what I'm trying to do because that question uses compile-time integers as template parameters, where I'm using types. It also concerns functions instead of classes. I feel like I'm close, but I just need some help to make my code work.
For reference, here is what I have for the other specializations (shortened):
template<class ReturnTy>
class Child<ReturnTy> : public Interface
{
public:
Child(ReturnTy default_value)
: // The same as first class without m_Args
{}
private:
// Same as first class without m_Args
};
template<class... ParamTypes>
class Child<void, ParamTypes...> : public Interface
{
public:
Child(ParamTypes... args)
: // Same as first class without m_ReturnValue
private:
// Same as first class without m_ReturnValue
};
Edit
Specifically, the issue comes from something like the following line of code:
Child<void> obj1(5);
The problem is that your specializations are of the same level (no one is more specialized that the other) and Child<void> matches both.
If you want that Child<void> matches the Child<ReturnTy> case (otherwise the solution is simple and elegant: in the second specialization, split the ParamTypes... list in a Par0 mandatory type and the rest of the ParamTypes...) I don't see a simple and elegant solution.
The best I can imagine, at the moment, is add a level of indirection (add a Child_base class) adding also a template parameter to explicit the desired solution.
Maybe can be made in a simpler way (sorry but, in this moment, I can try with a compiler) but I imagine something as follows
template <typename RT, bool, typename ... PTs>
class Child_base : public Interface
{
// general case (no empy PTs... list and no void return type)
};
template <typename ... PTs>
class Child_base<void, true, PTs...> : public Interface
{
// case return type is void (also empy PTs... list)
};
template <typename RT>
class Child_base<RT, false> : public Interface
{
// case return type only, but not void, and empy PTs
};
template <typename RT, typename ... PTs>
class Child
: public Child_base<RT, std::is_same_v<void, RT>, PTs...>
{
};
This way, Child<void> inherit from Child_base<void, true> that matches the first specialization of Child_base but doesn't match the second one.
I propose another way about Child: instead of define it as a class derived from Child_base, you can try defining it as a using alias of Child_base
template <typename RT, typename ... PTs>
using Child = Child_base<RT, std::is_same_v<void, RT>, PTs...>;
Maybe renaming Child_base with a more appropriate name.
issue is that Child<void> matches 2 (partial) specializations (where none are more specialized than the other):
template<class ReturnTy> class Child<ReturnTy> with [ReturnTy = void]
template<class... ParamTypes> class Child<void, ParamTypes...> with empty pack.
You so need extra specialization:
template<>
class Child<void> : public Interface
{
public:
Child() = default;
// ....
private:
std::function<void()> m_Function;
};
Demo

Enable if/else class member template instantiation

Can anyone tell my how to enable if/else class member template based on different derived classes from pre-defined base set? Let me use the following example:
enum class Type {
TYPEA,
TYPEB
};
// Predefined in libraries.
class BaseA {...};
class BaseB {...};
class Foo {
template <typename Derived, Type type>
void foo();
};
// User-derived
class DerivedA : public BaseA {};
class DerivedB : public BaseB {};
Normally we need two template typenames for calling the member foo.
Foo obj;
obj.foo<DerivedA, Type::TypeA>()
obj.foo<DerivedB, Type::TypeB>();
However, this native approach seems lengthy because the second template argument Type::TypeA and Type::TypeB can obviously be deduced by compiler through the first argument DerivedA and DerivedB, if they are derived from pre-defined base properly. I notice that c++11 provides is_base_of template but I am not sure how to use it in my case. To be more specific, below is the expected solution:
obj.foo<DerivedA>(); // Automatically deduce type = Type::TypeA
obj.foo<DerivedB>(); // Automatically deduce type = Type::TypeB
And if the compile fails to deduce the Type from the first typename, it should it just goes back to the normal declaration obj.foo<MyClass, MyType> where MyType is either Type::TypeA or Type::TypeB.
Sounds like you just want a default template argument:
class Foo {
template <typename Derived, Type type = get_type_from<Derived>::value>
void foo();
};
Where get_type_from<> is a metafunction to be filled in later based on how you actually figure out the Types.
template<Type t>
using etype_tag = std::integral_constant<Type, t>;
template<class T>
struct tag_t {
using type=T;
template<class D,
std::enable_if_t<std::is_base_of<T, D>::value, int>* =nullptr
>
constexpr tag_t( tag_t<D> ) {}
constexpr tag_t() = default;
constexpr tag_t(tag_t const&) = default;
};
template<class T>
constexpr tag_t<T> tag{};
constexpr etype_tag<Type::TYPEA> get_etype( tag_t<BaseA> ) { return {}; }
constexpr etype_tag<Type::TYPEB> get_etype( tag_t<BaseB> ) { return {}; }
template<class T>
constexpr decltype( get_etype( tag<T> ) ) etype{};
Now etype<Bob> is a compile-time constant integral constant you want.
class Foo {
template <typename Derived, Type type=etype<Derived>>
void foo();
};
makes the 2nd argument (usually) redundant.
You can extend get_etype with more overloads in either the namespace where etype is declared, or in the namespace of tag_t, or in the namespace of the type you are extending get_etype to work with, and etype will automatically gain support (assuming it is used in a context where the extension is visible: failure of that requirement leaves your program ill formed).
Live example

expanding parameter pack in templated constructor of templated class

Before I describe the problem I will give you an idea what is the target of my work.
I want to have a template which creates a class ( while do this unrolling a typelist recursively) which derives from all given types in a variadic list of parameters. That works fine. (see below)
Now is my target to provide all parameters to all constructors of the subclasses via an "automatic" created type from the unrolling template. Finally each of the Unroll classes should eat the parameters it needs to create a instance of the given classes. Each of the recursively created template instances should eat one of the parameter packs contained in the TypeContainer.
Before you ask: This code is only academic to learn new features of c++11. :-)
// create a wrapper around tuple to make it constructible with initializer list
template <typename ... T>
class TypeContainer: std::tuple<T...>
{
public:
TypeContainer(T... args):std::tuple<T...>(args...){};
};
// create a template to concatenate some typelists
// ??? is there a already usable template in std:: ???
template < typename ... X >
class TypeConcatenate;
template <typename T, typename ... S >
class TypeConcatenate < T, TypeContainer< S... >>
{
public:
typedef TypeContainer< T, S...> type;
};
// The follwing template unrolls a typelist and creates a recursively
// inherited class.
template <typename ... T> class Unroll;
template < class Base, class Head, class ... Next >
class Unroll< Base, Head, Next...>: public Unroll < Base, Next...>
{
public:
// collect all needed types for the instance creation of all child
// classes.
typedef typename TypeConcatenate<typename Head::Parms, typename Unroll < Base, Next...>::AllParms>::type AllParms;
};
template < class Base, class Head>
class Unroll < Base, Head>
{
// provide first parameter set for the constructor
public:
typedef TypeContainer<typename Head::Parms> AllParms;
};
template < class Base, class ... Next>
class Top : public Unroll < Base, Next...>
{
// I want to have a constructor which accepts
// all parameters for all the sub classes.
public:
template <typename ...T> Top(T... args);
};
// ??? The following lines of code will not compile!!!
// gcc 4.8.1 gives:
// error: ISO C++ forbids declaration of 'Top' with no type
// ??? Why the compiler could not interpret this as constructor ???
template <typename Base, typename ... Next, typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}
class Base {};
class A: public Base
{
public:
typedef TypeContainer<int, float> Parms;
A( int i, float f){}
} ;
class B: public Base
{
public:
typedef TypeContainer< char, int> Parms;
B( char c, int i){}
};
Top<Base, A, B> top {A{ 1,1},B{1,1}};
Questions:
1) Is there maybe a simpler way to determine the parameter list for the class
hierarchy. My way with typedef typename TypeConcatenate<typename Head::Parms, typename Unroll < Base, Next...>::AllParms>::type AllParms; looks a bit hard :-)
2) Because of 1) I have a kind of type container which holds T... and the problem with my constructor arise with the unpacking of the parameter list which is contained in a container. Maybe my solution is much to complex. Nay hint to solve the basic idea?
3) Ignoring that the problems of 1) and 2) are comes from a totally boring design I want to know which I couldn’t specialize the constructor with
template <typename Base, typename ... Next, typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}
For any further discussion: Yes, I know that the parameters should be forwarded and not given as value an so on. But I want to simplify the example which seems long enough for the discussion.
It sounds like you want a variadic forwarding constructor, something like:
template <typename... Ts>
class lots_of_parents : public Ts...
{
public:
template <typename... Args>
lots_of_parents(Args&&... args) : Ts(std::forward<Args>(args))... {}
};
lots_of_parents<A, B> mytop {A{1, 1}, B{1, 1}};
and either (a) the rest of the question is XY problem, or (b) I'm simply not understanding.
EDIT: Missed the question about your constructor. Ignoring for the moment that functions cannot be partially specialized, I think the syntax would look like:
template <typename Base, typename ... Next>
template <typename ... T>
Top<Base, Next...>::Top< TypeContainer<T...>>( T... args) {}
Which still doesn't really make sense, there's no way to deduce TypeContainer<T...> from T... args.

how to end-up template layers?

When having:
template <typename Super>
class Whatever : public Super
{
...
};
is it possible, to create Whatever class without deriving from something?
Is this the lighter version?
struct BlankType{};
Whatever<BlankType> w;
////////////////////////////////////////
Some background:
I have my code composed into template layers like Whatever above. So I can do:
typedef Whatever<Whenever<Wherever<>>>> MyCombinedType
actually I can not. I have to do
typedef Whatever<Whenever<Wherever<BlankType>>>> MyCombinedType
and the type becomes also BlankType.
I can not make Wherever "non-layerable", because when I would do just
typedef Whatever<Whenever<>>> MyCombinedType
the problem will appear again...
If you want to create Whatever class that is not derived from something you can simply define its specification as follows:
class BlankType {};
template<typename T = BlankType> class Whatever : public T {};
template<> class Whatever<BlankType> {};
A bit off-topic, in C++ with variadic templates you can avoid the recursive instantiation thanks to a recursive definition:
template <class ...Bases> class Whatever;
template <class B, class ...Bases>
class Whatever<B, Bases...> : public B, public Whatever<Bases...> { /* ... */ };
template <class B>
class Whatever<B> : public B { /*... */ };
template <> class Whatever<> { /* ... */ };
Now you can say Whatever<Foo, Bar, Baz> and inherit from all those. If you want to inherit also from multiply nested other instances of Whatever, you should make all the inheritances virtual.
The final specialization in my example also shows how you can specialize Whatever to not derive from anything. If you write Whatever<> x;, you have an object of a class that does not derive from anything.