Vladimir Ivannikov
Vladimir Ivannikov

Reputation: 149

Partial specialization C++

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

Answers (1)

463035818_is_not_an_ai
463035818_is_not_an_ai

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

Related Questions