Why can't I do this:
template<template<class E>class Derived>
struct X
{
static void f()
{
Derived<E>::value;
}
};
The problem that I have is that I cannot compile this code for the reason that I'm getting an error saying that param E hasn't been declared. Is there a way that I can use this formal param or not?
Parameters of template template parameters don't get arguments, and therefore don't usually have names. Partial specialization is the exception to this rule. Try this instead:
template<class> // Derived<E> is only only parameter
struct X; // but you actually need two parameters, Derived and E
template< template <class> class Derived, class E >
struct X< Derived< E > > // so use partial specialization.
{
static void f()
{
Derived<E>::value; // only reason to want this is to
Derived<int>::value; // use different specializations
}
};
Of course, if you don't need to re-specialize on Derived< something_else >, just ignore the fact that Derived<E> is a template specialization:
template<class Derived>
struct X
{
static void f()
{
Derived::value;
}
};
X< my_class< something > > my_x; // a specialized class template is a class
Your template parameter Derived is a template itself, E is its formal parameter.
You need to pass a value for it, too.
Maybe you need the following:
template<template<class E>class Derived, class T>
struct X
{
static void f()
{
Derived<T>::value;
}
};
You can't use that parameter because it is just there to mean that Derived is a template with exactly one type argument.
You'd call f like this:
template <class T>
struct ZZZ {};
X<ZZZ>::f();
^^^
Note that there is no E in this instantiation.
Unless there is a reason to use template templates, you could just use a regular template, else you'll need to pass E as a separate argument, making the call look like this:
X<ZZZ, int>::f();
You just have your syntax a bit muddled.
template<class E>
struct X
{
static void f()
{
Derived<E>::value;
}
}
should work fine.
Related
I have a class that works as wrapper for some primitives or custom types. I want to write explicit specialization for custom template type.
My code that reproduces the problem:
template < class T >
struct A {
void func() { std::cout << "base\n"; }
};
template <>
struct A<int> {};
template < class T, class CRTP >
struct BaseCrtp {
void someFunc() {
CRTP::someStaticFunc();
}
};
struct DerrType : BaseCrtp<int, DerrType> {
static void someStaticFunc() {}
};
template < class T, class CRTP >
struct A< BaseCrtp<T, CRTP> > {
void func() { std::cout << "sometype\n"; }
};
int main() {
A<DerrType> a;
a.func(); // print: "base". should be: "sometype"
return 0;
}
A<DerrType> use default function, not a specialization. How can I make specialization for these set of classes?
I will have a lot of types like DerrType, and I want to make common behavior for all of them.
DerrType and others will be used as curiously recurring template pattern
Not sure I fully understood what you want, but maybe something like this:
template<typename T>
concept DerivedFromBaseCrtp = requires(T& t) {
[]<typename U, typename CRTP>(BaseCrtp<U, CRTP>&){}(t);
};
template < DerivedFromBaseCrtp T >
struct A<T> {
void func() { std::cout << "sometype\n"; }
};
The concept basically checks whether T is equal to or is publicly inherited (directly or indirectly) from some specialization of BaseCrtp. Otherwise the call to the lambda would be ill-formed. Template argument deduction only succeeds in the call if the argument and parameter type match exactly or the argument has a derived type of the parameter. If the class is inherited non-publicly, the reference in the call can't bind to the parameter.
The concept will however fail if the type is inherited from multiple BaseCrtp specializations, in which case template argument deduction on the call will not be able to choose between the multiple choices.
Alternatively you can also use the stricter concept
template<typename T>
concept CrtpDerivedFromBaseCrtp = requires(T& t) {
[]<typename U>(BaseCrtp<U, T>&){}(t);
};
which will also require that the type T is actually using the CRTP pattern on BaseCrtp (directly or through a some base class between BaseCrtp and T). Again, this will fail if T is inherited multiple times from some BaseCrtp<U, T> specialization, although it will ignore specializations with a type other than T in the second position.
For another alternative you might want to check that T is derived from some type X such that X is derived from BaseCrtp<U, X> for some U (meaning that X uses the CRTP pattern correctly). That could be done using this variation:
template <typename T>
concept CrtpDerivedFromBaseCrtp =
requires(T& t) {
[]<typename U, typename CRTP>(BaseCrtp<U, CRTP>&)
requires(std::is_base_of_v<CRTP, T> &&
std::is_base_of_v<BaseCrtp<U, CRTP>, CRTP>)
{}
(t);
};
Again, this fails if T is derived from multiple BaseCrtp specializations, directly or indirectly.
So first, apologies for terminology - I'm not sure if template prototype is the correct term. By this I mean :
template <class T, class X>
class TemplatePrototype
{
// code
};
I have a situation where I have a function that creates a template object based upon template arguments to that function.
template <class T, class X>
void doSomething()
{
TemplatePrototype<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
However, there are about 15 different versions of TemplatePrototype, which all have the same interface but different execution (TemplatePrototype is provided by another library). As a result, I have a lot of code that looks like this:
template <class T, class X>
void doSomethingWithOne()
{
TemplatePrototypeOne<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
template <class T, class X>
void doSomethingWithTwo()
{
TemplatePrototypeTwo<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
As a consequence of the architecture, I must know which TemplatePrototype I am going to use before I know the actual types T and X. I would like to see something like this:
template <class T, class X, class Prototype>
void doSomething()
{
Prototype<T, X> aPrototype;
aPrototype.doSomething();
}
But where I have specified part of the template arguments in advance - i.e I specify Prototype before I know T and X. Obviously, this is not possible in C++.
Equally, I cannot pass the Prototype as a template argument because it will still result in huge amounts of duplicate code.
Some important facts : I know the range of all possible inputs.
So I could theoretically use a macro to define each possible template specialisation and insert them into a container, which I would then use to access the specialisation I need. However, I am looking for a more 'elegant' solution - is it possible to pass template prototypes without specialising them as an argument to a template class, and then instantiate later when a function is called? Example:
template <class Prototype>
class Holder
{
template <class T, class X>
void doSomething()
{
Prototype<T, X> aPrototype;
aPrototype.doSomethingElse();
}
};
As far as I know this is impossible, but I was wondering if the SO community had some folks who know a solution?
EDIT:
So I have implemented this as my solution, thanks to the answers below!
#include <iostream>
template <typename T>
struct Foo
{
Foo() { aPtr = 0; }
T* aPtr;
};
template <template<typename> class C>
struct Bar
{
template <class T>
void doSomething()
{
C<T> aClass;
if (aClass.aPtr)
std::cout << "Hello world" << std::endl;
}
};
int main()
{
Bar<Foo> aFoo;
aFoo.doSomething<int>();
return 0;
}
This enables me to specify which TemplatePrototype I wish to use, before I can know the template parameters.
Yes, use a template template parameter, e.g.
template <typename T>
struct Foo
{
};
template <template<typename> class C>
struct Bar
{
};
then
Bar<Foo> b;
You're looking for template template parameters.
In the template parameter list, instead of just:
class TemplatePrototype
specify your prototype as a class template which itself has two template type parameters (without giving them a name here), like:
template<class,class> class TemplatePrototype
//^^^^^^^^^^^^^^^^^^^
This will result in a function like:
template <class T, class X,
template<class,class> class TemplatePrototype>
void doSomething()
{
TemplatePrototype<T, X> aTemplateTX;
aTemplateTX.doSomethingElse();
}
Invocation example:
doSomething<T, X, TemplatePrototypeOne>();
To become independent of the number of template parameters you pass to your "prototype" (here it was 2, namely T and X), you can use variadic templates (since C++11).
For this, first move the prototype template parameter to the first position:
template <template<class,class> class TemplatePrototype,
class T, class X>
Then, replace class T, class X with class ...Ts, which is a placeholder of an arbitrary number of type parameters. Also, in the template template parameter list, replace class,class with class.... And in the instantiation within the function implementation, replace <T, X> with <Ts...> to "expand" the parameter pack.
The result then looks like this:
template <template<class...> class TemplatePrototype,
class ... Ts>
void doSomething()
{
TemplatePrototype<Ts...> aTemplateTs;
aTemplateTs.doSomethingElse();
}
Live demo
If I have a template class with a default template type, I have to write the template angle brackets. Is it somehow possible to avoid this?
Example:
template <typename T=int>
class tt {
public:
T get() { return 5; }
};
...
tt<> t; // how to avoid <>
std::cout << t.get() << std::endl;
Until now i've did this by a separate namespace and redeclaring the class:
namespace detail_ {
template <typename T=int>
class tt {
public:
T get() { return 5; }
};
}
class tt : public detail_::tt {}
...
tt t;
std::cout << t.get() << std::endl;
The problem is, if I want to use the class with an other type I have to go over namespace detail_. Is there another solution, which I didn't see yet.
... if I want to use the class ...
This is a common source of confusion. A class template is not a class, but a template from which classes are generated. The angle brackets is what tells the compiler that you want to generate a class out of the class template with the given template arguments, without the angle brackets what you have is a template.
template <typename T = int>
struct TemplateClass { /*...*/ };
template <template <typename> class T>
void f() {
T<int> t; // ...
}
template <typename T>
void g() {
T t; // ...
}
f<TemplateClass>(); // Accepts a template with a single type argument
g<TemplateClass<> >(); // Accepts a type, that can be generated out of the template
The language does not allow the coexistence of a template and a type with the same name in the same namespace, so the answer is that it cannot be done. You can create a type alias but you will have to give it a different name.
You can use typedef...
typedef tt<> tt_;
And then simply use tt_.
Since C++17, because of class template argument deduction, things have changed.
tt and tt<> are not the same thing: types and class templates were different and continue to be treated differently.
Anyway in simple scenarios like the one in your example, C++17 assumes what you mean and the <> aren't needed anymore.
Further details:
Template default arguments (specifically https://stackoverflow.com/a/50970942/3235496);
Why is <> required when specifying a template class which has defaults for all its template parameters?
I have tried to implement a "template template template" - template class to fullfill my needs ( I am quite new in using template metaprogramming). Unfortunately, I have found the following topic too late:
Template Template Parameters
Nevertheless, I need to implement something like listed below.
According to the compiler the last typedef is not working. I am not sure, but I think this is due to the limitation of 3x template restriction. Is there any possibility to bypass a 3xtemplate definition 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;
}
Thanks a lot, I really appreciate any help!
EDIT:
I have extended my listing (I am pretty sure it will not compile :)) to show the motivation why I am using my weird concept :)
There is really no need to pass template template parameter around
here. Usually you can just take a normal template argument and provide
a reasonable default:
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 done the same way for allocator aware containers.
And please do away with the horrible hungarian-notation prefixes.
NB: It seems from your usage of constructors and destructors that you
don't really have a grasp of basic C++. You might want to stay away
from templates before you have understood easier concepts.
Yes it is possible to avoid template template parameters (of any level).
A template is basically a type-level function. You feed it a type, and get another type back.
A template template parameter is itself a type-level function, and a template that accepts such parameter is a higher-order type-level function.
It is possible to implement higher-order type-level functions with member templates, without ever using template template parameters. I'm not really sure you need it for your design, but here's a quick and dirty example:
// regular type, a.k.a. zeroth-order type-level function,
// a.k.a. "type of kind *"
struct N
{
int a;
};
// a first-order type-level function, a.k.a. "type of kind *->*"
// it is wrapped in a regular type
struct B
{
template <class A> struct Impl
{
void foo(A a)
{
int aa = a.a;
}
};
};
// 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;
In this case you don't really need to have template parameters, basically the only variable type is TValueType right?
The other types can be resolved on the class body using TValueType.
Something like this:
template <
typename TValueType
>
class TAlgorithm
{
public:
// TTranslator <TValueType> whatever
// TTranslatorValueType <TValueType> whatever
TAlgorithm(){}
~TAlgorithm(){}
}
In templates as shown below, I would like the call Run(&Base::foo) succeed without the need to name the Base type twice (as is done in the compiling Run<Base>(&Base::foo) call). Can I have that? Possibly without adding a ton of Boost headers?
With the provided code, I get an error of:
prog.cpp:26: error: no matching function for call to ‘Run(bool (Base::*)())’
(you can fiddle with the snippet at http://ideone.com/8NZkq):
#include <iostream>
class Base {
public:
bool foo() { return true; }
};
Base* x;
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<typename T>
void Run(typename Traits<T>::BoolMethodPtr check) {
T* y = dynamic_cast<T*>(x);
std::cout << (y->*check)();
}
int main() {
Base y;
x = &y;
Run<Base>(&Base::foo);
Run(&Base::foo); // why error?
}
The T in Traits<T>::BoolMethodPtr is in a non-deduced context, so the compiler will not deduce automatically from the call what type T should be.
This is because there could be code like this:
template<typename T>
struct Traits {
typedef bool (T::*BoolMethodPtr)();
};
template<>
struct Traits<int> {
typedef bool (Base::*BoolMethodPtr)();
};
Run(&Base::foo); /* What should T be deduced to? Base and int are both equally possible */
If you can do without the Traits<T> class, you can write Run as:
template<class Class>
void Run(bool (Class::*check)()) {
Class* y = dynamic_cast<Class*>(x);
std::cout << (y->*check)();
}
In this context, Class can be deduced to mean Base
To pick apart a type, any type, use partial specialization. There is no function template partial specialization, so you'll need to directly parameterize the function on its argument type and retrieve the class type inside.
template< typename T >
struct get_host_class; // most types are not ptmfs: don't implement this
template< typename C >
struct get_host_class< bool (C::*)() > { // implement partial specialization
typedef C host;
typedef void sfinae; // disallow function for non ptmf arguments
};
template< typename T >
typename get_host_class<T>::sfinae Run( T check) {
typedef T BoolMethodPtr; // or something
typedef typename get_host_class< T >::host host;
}
I think this is a non deduced context.
$14.8.2.5/5- "The non-deduced contexts
are: — The nested-name-specifier of a
type that was specified using a
qualified-id."
I think this is the quote that applies in this case. But some template gods need to ratify my understanding.
When the compiler tries to match a template argument, it only considers the primary class type. In other words, when it encounters the expression:
Run(&Base::foo);
...and it's trying to figure out the template parameter for Run, it only considers the type of foo itself, and doesn't consider whatever class foo is a part of.
EDIT:
And the type of foo is bool(Base::*)(void), but what you want the compiler to find is just Base