I currently use a template class with multiple parameters,
template<class A, class B> class M{ };
However, in the position of class A I want to insert a template class, something like
template<class C> class A{ };
The only solution I've found for doing this is to use template template parameters:
template< template<class C> class A, class B> class M{ };
In my implementation, the only parameterization of A I use is A<B>. I don't need several instantiations of A using different parameters, for example I don't need to instantiate A<int> A<double> and A<long double> in M.
Is there an alternative to the template template parameter? The reason I ask is a follow up of this thread, in which in his answer #Evan Teran says he's only once ever had to use template template parameters...
I guess a twist on my question is: are there downsides to using template template parameters?
Assuming B can somehow be determined from A<B>, you can just take one template parameter:
template <class A> class M
{
typedef typename A::The_B_Type B;
};
Of course, The_B_Type has to be a valid typedef within A<B>. That's one of the reasons why standard library containers provide all the typedefs. For example, if the template A was std::vector, you could do this:
template <class A> class M
{
typedef typename A::value_type B;
};
You can take the instantiated A<B> as an argument, then use a traits class to extract the B passed to A<B> if you need it:
template<typename T>
struct extract_b {}; // SFINAE enabled
template<template<class>class A, typename B>
struct extract_b< A<B> > {
typedef B type;
};
// C++11, you can replace it with typename extract_b<T>::type at point of use
// if you lack support for it:
template <typename T>
using ExtractB = typename extract_b<T>::type;
template<typename A>
struct M {
typedef ExtractB<A> B;
// ...
};
the traits class is poorly named, but you can see that I can get the template argument out of A<B> and expose it in M<A>.
Related
Say I have a simple template like this:
template<typename T>
class A {};
And I want to specify that the type-parameter T is of some unrelated type X<U> where U is not known (or unspecifyable).
Is there a way how to express that as a concept?
Is there a way how to express that as a concept?
You don't need a concept, class template specialization works just fine in your case.
As an example, you can do this:
template<typename T>
class A;
template<typename U>
class A<X<U>> { /* ... */ };
This way, unless A is instantiated with a type of the form X<U> (where U is unknown), you'll get a compile-time error because the primary template isn't defined. In other terms, it won't work for all the types but X<U> (for each U), where the latter matches the class template specialization that has a proper definition.
Note that I assumed X is a known type. That's not clear from your question.
Anyway, if it's not and you want to accept types of the form X<U> for each X and each U, you can still do this:
template<typename T>
class A;
template<template<typename> class X, typename U>
class A<X<U>> { /* ... */ };
As a minimal, working example:
template<typename>
struct S {};
template<typename>
class A;
template<typename U>
class A<S<U>> {};
int main() {
A<S<int>> aSInt;
A<S<double>> aSDouble;
// A<char> aChar;
}
Both A<S<int>> and A<S<double>> are fine and the example compiles. If you toggle the comment, it won't compile anymore for A<char> isn't defined at all.
As a side note, if you don't want to use class template specialization and you want to simulate concepts (remember that they are not part of the standard yet and they won't be at least until 2020), you can do something like this:
#include<type_traits>
template<typename>
struct X {};
template<typename>
struct is_xu: std::false_type {};
template<typename U>
struct is_xu<X<U>>: std::true_type {};
template<typename T>
struct A {
static_assert(is_xu<T>::value, "!");
// ...
};
int main() {
A<X<int>> aXInt;
A<X<double>> aXDouble;
// A<char> aChar;
}
That is, given a generic type T, static assert its actual type by means of another structure (is_xu in the example) that verifies if T is of the form X<U> (for each U) or not.
My two cents: the class template specialization is easier to read and understand at a glance.
template <typename T, template <typename> class C>
concept bool Template = requires (T t) { {t} -> C<auto>; };
Now given a class template:
template <typename T>
struct X {};
a type template parameter can be constrained using:
template <typename T> requires Template<T, X>
class A {};
or:
template <Template<X> T>
class A {};
DEMO
This will work also for types derived from X<U>.
I have created a template class which takes two plain template parameters (like int or double) and have derived several other classes from it:
template <typename A, typename B>
class IClassBase {...}
template <typename B>
class Derived1Class : public IClassBase<std::string, B> {...}
template <typename B>
class Derived2Class : public IClassBase<std::string, B> {...}
I need to design a structure which would allow compiler to build a std::tuple based on list of template types and their parameters (B type in code snippet above).
So given the list below
Derived1Class<int>, Derived1Class<double>, Derived2Class<bool>, Derived2Class<std::string>
compiler should infer following tuple:
std::tuple<int, double, bool, std::string>
Is this even possible, and if so, how it can be done in C++?
Thanks in advance)
Is this even possible, and if so, how it can be done in C++?
Anything is possible in C++. Especially the current C++ standard. Tested with gcc 6.2.
#include <tuple>
#include <string>
template<typename template_type> class extract_param;
template<template<typename T> typename template_param, typename template_param_t>
class extract_param<template_param<template_param_t>> {
public:
typedef template_param_t type_t;
};
template<typename ...Args>
using extract_tuple=std::tuple<typename extract_param<Args>::type_t...>;
template<typename T> class sometemplate {};
int main()
{
extract_tuple< sometemplate<int>, sometemplate<std::string>> tuple;
int &intref=std::get<0>(tuple);
std::string &stringref=std::get<1>(tuple);
return 0;
}
I have code where I want to typedef a templated class for easier reading:
template<int A, int B>
using templateClass = templateClass<A,B>;
void aFunction(templateClass& tc);
int main(){
templateClass<10, 34> tc;
aFunction(tc);
}
void aFunction(templateClass& tc){
...
}
but I get many errors regarding the template identifiers not being found. How should this be done? I was trying to follow this example:
How to typedef a template class?
An alias template is useful when you only know some template parameters in advance:
template <class Value>
using lookup = std::map<std::string, Value>;
lookup<int> for_ints;
lookup<double> for_doubles;
It is unclear in your case whether you want a different name for a class template:
template <class A, class B>
class templateClass;
template <class A, class B>
using otherName = templateClass<A, B>;
if you already know the types you need:
typedef templateClass<int, double> int_double;
or if you just know one type:
template <class B>
using with_int = templateClass<int, B>;
In any case, you cannot have an alias with the same name as a class, like you're doing for templateClass.
templateClass is not a type; it's a type template. You still need to use the template keyword when defining templated functions with it.
template<int A, int B>
void aFunction(templateClass<A, B>& tc);
Having a class like the A, is there a way to apply it to a template like this of B, with T2 set to some type C? But without creating another template class inheriting from A.
template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
With C++11 using a template alias works:
template<typename T1, typename T2>
class A
{ };
template<template <typename T1> class T3>
class B
{ };
class C
{ };
template< typename T > using A1 = A< T, C >;
int main()
{
B< A1 > b;
}
without C++11, you are left with what you probably already know:
template< typename T > class A1 : A< T, C > {};
I will propose an alternative solution: do not use template template parameters.
If you write:
template <typename T> struct B {};
Then it can be used with A<int, int> or C<3> or even plain D.
Whilst it is possible to use template template parameters, it is general a bad idea. You should treat the template parameter of a class as an implementation detail and apply the golden rule: do not rely on implementation details.
If you need access to the type, somehow, then use an associated type (aka T::AssociatedType) or a trait (BTraits<T>::AssociatedType).
EDIT: dealing with multiple instantiations of the template template parameter.
Suppose we want to "erase" the template template parameter of such a class:
template <template <typename> class A>
struct Something {
template <typename T>
void doit() { A<T>::doit(); }
};
The C++ standard allocation model is to use an inner rebind structure:
template <typename T>
struct Simple {
template <typename U>
struct rebind { typedef Simple<U> type; };
};
template <typename T0, typename T1>
struct Multi {
template <typename U>
struct rebind { typedef Multi<U, T1> type; };
};
template <typename A>
struct Something {
template <typename T>
void doit() { typedef typename A::rebind<T>::type B; B::doit(); }
};
Note how you can use complex computations in rebind and nothing forces you in blindly passing the type received as parameter.
Whilst another (similar) solution is to ask for a factory (aka, the object passed itself cannot be used but it can build useful objects); for ease of use the C++ containers ask of their allocators that they be both usable in themselves and factories for other types.
Yes, you can do it using C++11's alias template:
template <typename T>
using AA = A<T, C>;
B<AA> b;
Live example
Is there some way to partially bind a template to parameter types? For example, I have the following template:
template<typename T, typename Q> struct generic { };
And I have another template which takes a template class as a parameter, expecting to be able to create instances of it with the first type:
template<typename T, template<typename> class Impl>
struct wrapper {
Impl<T> foo;
};
This would accept a simple template like template<typename T> without changes. What I want to do now is partially bind the generic template, specifying only Q and passing it to wrapper. Making up some syntax, perhaps something like this:
template<typename T> bound = generic<T,some_type>;
I know I can almost get what I want using inheritance:
template<typename T> bound : public generic<T,some_type> { };
I am hoping though to avoid this though as it causes issues with constructors and operators defined in the base class.
In C++11 you can use template aliases
template<class X>
using Bind_CPP11 = generic<X, Y>;
template<class X, template<class> class Impl>
struct wrapper_CPP11
{
Impl<X> foo;
};
In C++98/03, you can use simple class composition (I would not use inheritance here)
template<class X>
struct Bind_CPP03
{
typedef generic<X, Y> type;
};
template<class X, template<class> class Impl>
struct wrapper_CPP03
{
typename Impl<X>::type foo;
// ^^^^^^^^ to extract dependent type
};
Live Example.