I'm working on the following idea:
There exists a generally abstract templated base class with mutiple template parameters. This class defines a contract guaranteeing the presence of certain methods i.e. a method getMax(). This method among others is generally purely virtual. Except there are special cases in which a sensible implementation can be given without the need to implement it manually every time in a derived class. So basically what I'm trying to achive is to (partially) implement the contracted methods already inside the abstract base class if the template arguments allow this.
I made a small example to illustrate the idea. (Note: The example is not perfect, for instance the implementation for std::string is very special and already implicitly forces TSize to be std::size_t)
#ifndef ABSTRACTBASE_H
#define ABSTRACTBASE_H
#include <type_traits>
#include <string>
#include <limits>
template <typename TSize, typename TVal1, typename TVal2>
class AbstractBase
{
public:
AbstractBase(){};
virtual ~AbstractBase() {};
virtual TSize getMax() const = 0; // <-- getMax should be generally
// purely virtual.
private:
TVal1 value1;
TVal2 value2;
};
//except when TVal1 is an arithmetic type in that case the following definition
//shall become active.
template <typename TSize,
typename TVal1,
typename TVal2,
typename = typename std::enable_if<std::is_arithmetic<TVal1>::value, TSize>::type>
TSize AbstractBase<TSize, TVal1, TVal2>::getMax()
{
return std::numeric_limits<TVal1>::max();
}
//... or when TVal1 is a string where this defintion makes sense
template <typename TSize,
typename TVal1,
typename TVal2,
typename = typename std::enable_if<std::is_same<TVal1, std::string>::value, TSize>::type>
TSize AbstractBase<TSize, TVal1, TVal2>::getMax()
{
return value1.max_size();
}
//... in all other cases the getMax() method shall stay purely virtual and an
//appropriate definition must be implemented inside a derived class
#endif //ABSTRACTBASE_H
#include "AbstractBase.h"
#include <string>
#include <iostream>
int main()
{
AbstractBase<int, int, int> arthBase();
AbstractBase<std::size_t, std::string, long> alphaBase();
std::cout << arthBase.getMax() << std::endl;
std::cout << alphaBase.getMax() << std::endl;
}
So I guess what is missing here is a method to actually also alter the declaration ov getMax() as virtual, though im not really sure if/how this is possible using type_traits.
Side note: I haven't worked with type traits very much yet. I know about the SFINAE principle behind it, which basically states that if the substitution for a template parameter fails the following code will be excluded from compilation rather than causing an error. What I haven't found out if the type_trait argument responsible for enabling/disabling the method has to be merged into the class template argument list like I did above, or if it is legal/possible to provide the type trait arguments in a seperate template argument list. In this case I guess it is impossible because the enable_if statement tests the classes template arguments which have to be declared/valid in this context.
Just in case you use really sophisticated type trait magic a more elaborate comment on that part is greatly appreciated.
Aucun commentaire:
Enregistrer un commentaire