Typedef a template argument - c++

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);

Related

Partial template instanciation

If I have this two template classes:
template<int a, typename V>
class A {
};
template<template<int, typename> typename V>
class B {
};
I can write something like B<A> a;.
How can I achieve a similar thing for this two classes:
template<int a, typename V>
class A {
};
template<template<typename> typename V>
class B {
};
I want to declare a variable like this B<A<1>> a;, but it says that A needs 2 parameters, which would be correct for an instance of A, but I only want to create a new template with a smaller number of parameters.
How can I achieve this?
You can't do this directly, but you can create a helper template using and pass it to B.
template <int N>
struct foo
{
template <typename T>
using type = A<N, T>;
};
B<foo<42>::type> x;

How to obtain inner type of template type?

I've got the following situation:
This is a wrapper type
template <typename wrapperInnerType>
struct wrapperT{ ... };
using wrapper = wrapperT<float>;
And it's used in this class
template <typename wrapperType>
class InData{
wrapperInnerType var; //<-- How to get inner type?
};
My question is what is the easiest way to get wrapperInnerType from wrapperType?
Ideally I would like it to be still possible to use InData<wrapper> myData; when using that class (instead of having multiple types in declaration like in InData<wrapper, float> myData; as an example).
The easiest way is to define a type alias in wrapperT.
template <typename wrapperInnerType>
struct wrapperT {
using innerType = T;
// ...
};
using wrapper = wrapperT<float>;
template <typename wrapperType>
class InData{
typename wrapperType::innerType var;
};
Another approach could be to make a helper struct that extract it using a template template parameter and partial specialization. This would avoid having to modify wrapperT and could potentially give some re-usability. The template signature of wrap would however have to be known for this to work.
template <typename T>
struct getInnerType;
template <template <typename> typename wrap, typename Inner>
struct getInnerType<wrap<Inner>> {
using type = Inner;
}
template <typename T> // For more convenient use as pointed out in comments
using getInnerType_t = typename getInnerType<T>::type
template <typename wrapperType>
class InData{
getInnerType_t<wrapperType> var; //<-- How to get inner type?
};
You could declare the following class template, wrapper_inner_type:
template<typename>
struct wrapper_inner_type;
Then, specialize it for the wrapper, wrapperT<InnerType>, where InnerType is the type you want to find out:
template<typename InnerType>
struct wrapper_inner_type<wrapperT<InnerType>> {
using type = InnerType;
};
You can also define this alias template for convenience:
template<typename T>
using wrapper_inner_type_t = typename wrapper_inner_type<T>::type;
Finally, in order to get the inner type inside InData:
template <typename wrapperType>
class InData{
wrapper_inner_type_t<wrapperType> var;
};

Partial Specialization using a qualified name

I'm trying to partially specialize a template for a metafunction and ran into a problem.
I specialized the template like this:
template <typename A, typename B>
struct Foo;
template <typename A, typename B1>
struct Foo<A, typename A::template Bar<B1>> {
/* use both A and B1*/
};
template <typename A, typename B1>
struct Foo<A, typename A::template Xyz<B1>> {
/* use both A and B1*/
};
However this results (Visual Studio 2019) in
Error C2764: 'B1': template parameter not used or deducible in partial specialization 'Foo<A,A::Bar<B1>>' (5, 47)
I assume this is because I used the template parameter A as a qualifier in the specialication (typename A::template Bar<B1>).
Is there any way to circumvent this and use parameters in template specializations as qualifiers?
Note: In my usecase the first parameter is never really specialized.
Theoretically it could work to nest the specialized template in another template class (i.e. currying the metafunction), but templates can only be specialized at namespace scope.
Using a template template parameter may work out:
template <typename A, typename B>
struct Foo;
template <typename TA, template<class> class TBar, typename B1>
struct Foo<TA, TBar<B1>> {};
Given
struct A
{
template<class T>
struct Bar {};
};
you can form
Foo<A, A::Bar<int>> x;
and it will deduce A, A::Bar and int in the specialization for you. But note that no attempt is made to check that the A in A::Bar matches the A given as first template parameter; it's unclear what you'd expect to happen for, say, a Foo<double, A::Bar<int>>.
https://godbolt.org/z/hGhsZm
I assume this is because I used the template parameter A as a qualifier in the specialication (typename A::template Bar).
I don't think so.
Suppose A is as follows
struct A
{
template <typename B>
using Bar = int;
};
and that you define a Foo<A,A::Bar<B1>>.
But A::Bar<B1> is int !
So you're defining Foo<A, int>.
How can, the compiler, deduce B1 from int ?
It seems to me that it can't.
Possible solution (depending from your needs): if you need to specialize through B1, but you need A::Bar<B1> inside Foo, you can use B1 itself as second parameter and A::Bar<B1> as using type inside Foo
template <typename A, typename B1>
struct Foo<A, B1> {
using bType = A::template Bar<B1>;
};

How to get a tuple based on list of template templates of variable size in C++?

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;
}

Alternatives to using template template parameters

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>.