How to avoid template template template template in C ++

I tried to implement a template template template - a template class to fill my needs (I'm completely new in using template metaprogramming). Unfortunately, I found the following topic too late: Template template options

However, I need to implement something like the ones listed below.

According to the compiler, the last typedef does not work. I am not sure, but I think this is due to limiting the restriction of the three patterns. Is there any way around the definition of 3xtemplate in this simple example?

template < typename TValueType > class ITTranslator { public: ITTranslator() = 0; virtual ~ITTranslator() = 0; virtual void doSomething() = 0; } template < typename TValueType > class TConcreteTranslator1 : public ITTranslator<TValueType> { public: TConcreteTranslator1(){} ~TConcreteTranslator1(){} void doSomething() {} } template < typename TValueType > class TConcreteTranslator2 : public ITTranslator<TValueType> { public: TConcreteTranslator2(){} ~TConcreteTranslator2(){} void doSomething() {} } template < typename TValueType, template < typename TValueType > class TTranslatorValueType > class ITClassifier { public: ITClassifier() = 0; virtual ~ITClassifier() = 0; } template < typename TValueType, template < typename TValueType > class TTranslatorValueType > class TConcreteClassifier1 : public ITClassifier<TValueType,TTranslatorValueType > { public: TConcreteClassifier1() {} ~TConcreteClassifier1() {} void dodo(){} } template < typename TValueType, template <typename TValueType> class TTranslatorValueType, template <template<typename TValueType> class TTranslatorValueType> class TClassifierValueType > class ITAlgorithm { public: ITAlgorithm()=0; virtual ~TAlgorithm()=0; virtual run() = 0; } template < typename TValueType, template <typename TValueType> class TTranslatorValueType, template <template<typename TValueType> class TTranslatorValueType> class TClassifierValueType > class TConcreteAlgorithm1 : public ITAlgorithm<TValueType,TTranslatorValueType,TTranslatorValueType> { public: TConcreteAlgorithm1 (){} ~TConcreteAlgorithm1 (){} run() { TClassifierValueType< TTranslatorValueType>* l_classifier_pt = new TClassifierValueType< TTranslatorValueType>( ); // add this object to a internal list... } } int main() { typedef TConcreteTranslator1< cvbase::uint32_t > translator_t; typedef TConcreteClassifier1< cvbase::uint32_t, TConcreteTranslator1> classifier_t; typedef TConcreteAlgorithm1 < cvbase::uint32_t, TConcreteTranslator1, TConcreteClassifier1> algorithm_t; // not possible return 0; } 

Thank you very much, I really appreciate any help!

EDIT: I expanded my list (I'm sure it won’t compile :)) to show the motivation why I use my weird concept :)

+4
source share
3 answers

There is no need to pass a template template parameter around here. You can usually just accept the normal template argument and provide a reasonable default value:

 template<typename ValueType> struct translator {}; template<typename ValueType, typename Translator = translator<ValueType>> struct Classifier {}; template<typename ValueType, typename Translator = translator<ValueType>, typename Classifier = classifier<ValueType, Translator> > struct Algorithm {}; 

This is the same as for containers supporting the dispenser.

And please remove the horrible Hungarian designations.

NB: It seems from your use of constructors and destructors you actually don't have an understanding of basic C ++. You might want to stay away from templates before you understand more understandable concepts.

+2
source

Yes, you can avoid the template parameters of the template (at any level).

A template is basically a level function. You feed it with a type and return another type.

The template template parameter itself is a level level function, and the template that takes such a parameter is a higher level level function.

You can implement higher-level functions with member templates without using the template template parameters. I'm not sure if you need this for your design, but here's a quick and dirty example:

 // regular type, aka zeroth-order type-level function, // aka "type of kind *" struct N { int a; }; // a first-order type-level function, aka "type of kind *->*" // it is wrapped in a regular type struct B { template <class A> struct Impl { void foo(A a) { int aa = aa; } }; }; // a second-order type-level function // that accepts a (wrapped) first-order type function // and also a regular type. the kind of it would be (*->*)->*->* // it applies its first argument to its second argument struct Z { template <class X, class Y> struct Impl { typename X::template Impl<Y> ya; void bar() { ya.foo(Y()); } }; }; // now this is something: a third-order type-level function // that accepts a (wrapped) second-order type-level function // and a (wrapped) first-order type-level function // and a zeroth-order type-level function // it applies its first argument to its second and third arguments // it is also wrapped in a regular type for consistency // try to figure out its kind struct T { template <class P, class Q, class R> struct Impl { typename P::template Impl<Q, R> yb; void baz() { yb.bar(); } }; }; T::Impl<Z, B, N> tt; 
+1
source

In this case, you really don't need the template parameters, basically the only variable type is TValueType? Other types can be resolved in the class class using TValueType.

Something like that:

 template < typename TValueType > class TAlgorithm { public: // TTranslator <TValueType> whatever // TTranslatorValueType <TValueType> whatever TAlgorithm(){} ~TAlgorithm(){} } 
0
source

Source: https://habr.com/ru/post/1440401/


All Articles