Reputation: 149
Good day!
I am trying to build a template class with its several partial specializations as follows:
#include <iostream>
struct MainT {};
struct Foo {};
template <int dim>
struct Tensor {};
template <int dim>
struct Bar {
using Sub = Tensor<dim>;
};
template<typename T, typename R>
struct A {
A() { std::cout << "A<T,R>" << std::endl; }
};
template<typename T>
struct A<T, Foo> {
A() { std::cout << "A<T,Foo>" << std::endl; }
};
template<typename T, int dim>
struct A<T, Bar<dim>> {
A() { std::cout << "A<T,Bar<dim>>" << std::endl; }
};
template<typename T, int dim>
struct A<T, typename Bar<dim>::Sub> {
A() { std::cout << "A<T,Bar<dim>::Sub>" << std::endl; }
Tensor<dim> t;
};
int main() {
A<MainT,double> a1; // OK
A<MainT,Foo> a2; // OK
A<MainT,Bar<2>> a3; // OK
A<MainT,Bar<2>::Sub> a4; // error: template parameters not deducible in partial specialization, note: 'dim'
return 0;
}
The 4th specialization fails to compile. I can not get why it does so. Could you please give a hint on where to look at to understand why it happens and possible solutions?
Upvotes: 0
Views: 71
Reputation: 122458
There is no 1:1
relation between Bar<dim>::Sub
and dim
as there is between Bar<dim>
and dim
.
Consider you are a compiler.
I tell you Bar<2>
, then you know "ah ok, they want dim=2
". That is: Given Bar<2>
you can deduce dim=2
.
I tell you Tensor<42>
, then you cannot possibly know that I actually meant the Tensor<42>
that is aliased as Bar<42>::Sub
. It could be that Bar<24>::Sub
, via a specialization, is the exact same type.
More formally, as SergeyA mentions in a comment, Bar<dim>::Sub
is a so-called non-deduced context. For details I refer you to What is a nondeduced context?.
Upvotes: 4