How to enforce contract on template parameter - c++

How can I specify template parameter to be of a certain type i-e it must have implemented an interface (the template parameter must be a derived class of a specific base class)
Heres the interface (abstract base class)
class baseActionCounter{
public:
virtual int eat()=0;
virtual int drink()=0;
};
Now I want my template parameter to be of type baseActionCounter
Heres the templated class
//imaginary template syntax in the line below. Is there a way of achieving this behavior?
template <class counterType : baseActionCounter>
class bigBoss{
counterType counter;
public:
int consumerStats(){
//I am able to call member function because I know that counter object has eat() and drink()
//because it implemented baseActionCounter abstract class
return counter.eat() + counter.drink();
}
};
I can also just derive my bigBoss class from baseActionCounter but I want to know how to achieve this behavior with templates.
Also, template specialization is not suitable as there is just one BigBoss class for any implementor of baseActionCounter class.

Yes, you can use std::is_base_of to check the type, e.g.
template <class counterType, std::enable_if_t<std::is_base_of_v<baseActionCounter, counterType>>* = nullptr>
class bigBoss {
Or
template <class counterType>
class bigBoss {
static_assert(std::is_base_of_v<baseActionCounter, counterType>, "counterType must derive from baseActionCounter");
...
};
Or use concept (since C++20).
template <class T>
concept Derived = std::is_base_of_v<baseActionCounter, T>;
template <Derived counterType>
class bigBoss {
BTW: std::is_base_of also returns true if the base class baseActionCounter is specified; if that's not what you want you can combine the condition with std::is_same.

Related

How do I use all instances of a templated class?

So I have a simple template class with multiple classes inheriting different types of it.
template<typename T> class root {
T value;
};
class body : public root<int> {
/* some code */
};
/*some more classes that inherits root*/
and later down in the file, I need to reference all classes that inherits from root
concept _bcie = std::is_base_of_v<root, body>
and it gives me the error use of class template 'root' requires template arguments
But I want to reference ALL classes that inherits from the root
Is there a way to just use the class without providing a template argument?
Make root derive from another higher non-template base class, and check against that class.
The simple way is to use template lambda
template<typename T>
class root {
T value;
};
template<class T>
concept is_derived_from_root = requires (const T& t) {
[]<class U>(const root<U>&){}(t);
};
Demo

How to overload a method of base class passed as a parameter to a template class in C++?

There are two classes:
class A {
public:
virtual void foo( int bar );
}
class B {
virtual void foo( string bar, int baz);
}
Now, the class(es) I'm building can derive from either class. But there's some common helper code, so I want to factor it out into a base class.
This common code must be called from foo and should take same arguments as the corresponding foo method. So I declare this template class, but don't know, whether it is possible to "extract" foo's signature from the template argument (which is a base class -- either A or B):
template<class Base>
class CommonBase : public Base {
public:
// how do I overload Base::foo here?
void foo(/*Base::foo arguments here*/) {
commonCode(/*Base::foo arguments here*/);
}
protected:
// how do I define commonCode with Base::foo signature below?
void commonCode(/*Base::foo arguments here*/) { ... }
}
I have little experience with C++ templates, so wondering -- is it even possible?
One solution I see is to add another template parameter for method signature and pass it explicitly when specializing. But it feels redundant as the knowledge of foo signature will be already contained in the Base class parameter (and compilation should fail if Base does not provide foo at all).
One solution I see is to add another template parameter for method signature and pass it explicitly when specializing.
This is on the right track, but you don't have to pass it explicitly; you can extract the type from the base class:
template<class Base, class... Arg>
class CommonBaseImpl : public Base {
public:
// how do I overload Base::foo here?
void foo(Arg... arg) override {
commonCode(std::forward<Arg>(arg)...);
}
protected:
// how do I define commonCode with Base::foo signature below?
void commonCode(Arg... arg) { ... }
};
template <class Base, class Foo = decltype(&Base::foo)>
struct BaseSelector;
template <class Base, class... Arg>
struct BaseSelector<Base, void (Base::*)(Arg...)>
{
using type = CommonBaseImpl<Base, Arg...>;
};
template <class Base>
using CommonBase = typename BaseSelector<Base>::type;
[Live example]
This works by using class template partial specialisation to decompose the function type. The template parameter Foo of BaseSelector will hold the type of member pointer to foo. To get this type, we use decltype(&Base::foo), the default argument for that parameter.
However, we need to access the individual argument types from within that type. This is normally done using template partial specialisation, as here. Basically, the primary template says: "This class template takes two types, Base and Foo." They're types and we know nothing more about them. We also don't use them for anything (the primary template is not even defined).
Then, we provide a specialisation. That effectively says: "When the type Foo happens to be a pointer to member function of Base which returns void and takes arguments of type Arg..., then do this: { partially specialised class definition }". In practice, it's just a way to assign names to the various components of the pointer-to-member type.

Curiously recurring templates with template leaf classes

I am thinking about using curiously recurring template pattern for my application. However, I would like the classes to operate on the user defined types. I would like to understand if it is possible to create a structure similar to the one shown below:
template <class T_leaftype>
class BaseTrajectoryPoint {
};
template <class MyType>
class MyTrajectoryPoint: public BaseTrajectoryPoint<MyTrajectoryPoint> {
private:
MyType A;
};
The code above fails to compile with the following error:
type/value mismatch at argument 1 in template parameter list for ‘template class BaseTrajectoryPoint’
Are there any alternative ways of approaching the problem? I would like to use static polymorphism, but I would prefer to define all possible methods in the base class.
template <class T_leaftype>
class BaseTrajectoryPoint {
};
template <class MyType>
class MyTrajectoryPoint: public BaseTrajectoryPoint<MyTrajectoryPoint<MyType> > {
private:
MyType A;
};
MyTrajectoryPoint isn't a type, it's template; when you pass it as template parameter, it's seen as template<typename> class T>, not template<class T> - and the latter is what your base class is expecting. But MyTrajectoryPoint<MyType> names a type, so you can use it as template parameter of your base class.
Of course, you can change declaration of BaseTrajectoryPoint to template<template<class> class T_leaftype>, but then you would have to use class template as template parameter, never a complete type.
What our friend Griwes said is correct, although if you know that every class that will inherit BaseTrajectoryPoint is a template class, you can do the following:
template<template < class > class TLeaf> // << This means: It is expected a template class as parameter
class BaseTrajectoryPoint{
};
template <class MyType>
class MyTrajectoryPoint: public BaseTrajectoryPoint<MyTrajectoryPoint> >{
private:
MyType A;
};

Recursive template

Is it possible to write template definition for this data type?
myclass<int, myclass<int> > data;
Second template variable should be optional with default value of the same type.
Clarification
Now I use this definition:
class defaultClass { };
template <typename T, typename C=defaultClass>
class myclass { ... };
I'd like to predefine that defaultClass is myclass<T>
I'd like to implement something like auto implemented properties: the second parameter should be context in which the wrapped variable is defined. If the context is ommited, it should be in the object created by the template class itself. (I realize it could be solved another way, this is just use case.)
Looks very similar to
http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
You can do the thing you want by making a class hierarchy with template base type and then each of your classes may be derived from that base like
template<class T> class base { ... };
class derived: public base<derived> {...};

Abstract class accessing the implemented type through a templated virtual function?

I was wondering if there could be any way to write a template function in an abstract class, and have it (the template function) automatically instantiated with the type of the derived class?
So you have a class that looks something like this
class A
{
virtual template < typename T>
void vtfunc(void)
};
class B : public A
{
/// No declared members pertaining to this example
}
Then, whenever a class derived from A is declared, it compiles "vtfunc" with itself as the template parameter T.
Then, calling vtfunc() through an interface of A calls the isntance of that function compiled for its derived class B.
Is there any way of doing this, or writing something fiddley that have this effect?
Obviously I am aware that the template parameter could only affect the internals of the class, and not the return type and parameters - they would need to be the same because of the way polymorphism works.
I’m not sure what you’re after but one common pattern is the so-called curiously recurring template pattern; here, the base class itself is the template, not its member functions. In other words:
template <typename T>
class A
{
virtual void vtfunc(void)
};
class B : public A<B>
{
…
};
Consider using a non-member function instead.