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.
You can use template specialization to help you deduce the type of your second argument (this can easily be extended to other specializations too):
#include <type_traits>
namespace details
{
// in allmost all cases we want to imply type int for the second argument
template<typename type_t>
struct deduced_second_arg_t_helper
{
using type = int;
};
// except for float, so use a template specialization to deduce a float
template<>
struct deduced_second_arg_t_helper<float>
{
using type = float;
};
// shorthand like
template<typename type_t>
using deduced_second_arg_t = typename deduced_second_arg_t_helper<type_t>::type;
}
// now the second argument can be deduced from the first
template<typename type_t, typename second_arg_t = details::deduced_second_arg_t<type_t>>
struct A
{
second_arg_t some_value;
};
// or simplified, we use the deduced type internally
template<typename type_t>
struct B
{
using some_value_t = details::deduced_second_arg_t<type_t>;
some_value_t some_value;
};
struct X
{
};
int main()
{
A<X> a_x;
A<float> a_f;
static_assert(std::is_same_v<decltype(a_x.some_value), int>);
static_assert(std::is_same_v<decltype(a_f.some_value), float>);
B<X> b_x;
B<float> b_f;
static_assert(std::is_same_v<decltype(b_x.some_value), int>);
static_assert(std::is_same_v<decltype(b_f.some_value), float>);
return 0;
}