I would like to define two particular default cases for a template class A.
Is something similar possible?:
template<typename T1, typename T2>
class A{
// ...
};
struct X;
// if necessary, I can also define X right here.
template<>
A<X> = A<X,int>;
template<typename T>
A<T> = A<T,T>;
int main(){
A<X> a; // shall construct an instance of A<X,int>
A<float> b; // shall construct an instance of A<float,float>
}
I see how it can be done by using a derived of A. However, I would hope that it is also possible in a similarly straight-forward way to the one presented in the non-functioning snippet above.
>Solution :
If A<X,..> is the only special case you can use std::conditional_t:
#include <type_traits>
template <typename T1,typename T2>
class A_impl {};
struct X {};
template<typename T1>
using A = A_impl<T1,std::conditional_t< std::is_same_v<T1,X>, int,T1>>;
int main(){
A<X> a; // shall construct an instance of A<X,int>
A<float> b; // shall construct an instance of A<float,float>
}
I tried to keep your A intact with 2 template arguments. Actuallly if possible, I would drop the second argument and instead use a member alias for T2 when T2 is always determined from T1:
#include <type_traits>
struct X {};
template<typename T1>
struct A {
using T2 = std::conditional_t< std::is_same_v<T1,X>, int,T1>;
};
int main(){
A<X> a; // shall construct an instance of A<X,int>
A<float> b; // shall construct an instance of A<float,float>
}
When A<X,...> is not the only special case you can still use std::conditional but it will get hairy quickly. For a general mapping from T1 to T2 I’d rather define a trait T2_from_T1_t that can be specialized accordingly.