Наследование шаблонов С++ скрывает параметры шаблона

template <typename>
struct B
{
    constexpr static int T = 5;
};

template <int T>
struct D : B<int>
{
    constexpr static int value = T;
};

int main()
{
    std::cout << D<7>::value << std::endl; // 5, how to get 7 ?
}

демонстрация

Как я недавно узнал, параметры шаблона производного класса шаблона проверяются после имен в базовом классе во время поиска. При этом, все равно, чтобы квалифицировать value инициализации имени T чтобы ссылаться на параметр шаблона T производного класса?

РЕДАКТИРОВАТЬ:

До сих пор от обсуждений в комментариях кажется, что единственный способ добиться этого - сделать зависимый тип/значение базового класса, который задержит поиск к именам базы (к фазе создания) и, таким образом, сделает единственное доступное значение для T - параметр шаблона.

Ответы

Ответ 1

Я не совсем уверен, что понимаю этот вопрос, но я думаю, что decltype делает то, что вы хотите:

template <int T>
struct D : B<decltype(T)>
{
    constexpr static decltype(T) value = T;
};

Ответ 2

Поскольку B является шаблоном, вы можете изменить его, чтобы сделать его зависимым базовым классом D:

template <typename, int = 0>
struct B {
    constexpr static int T = 5;
};

template <int T>
struct D : B<int, T> {
    constexpr static int value = T; // name lookup of base T is deferred
};

Ответ 3

Чтобы ссылаться на значение T шаблона B (которое не зависит от параметра шаблона B):

#include <iostream>

template <typename>
struct B
{
    constexpr static int T = 5;
};

template <int T>
struct D : B<decltype(B<void>::T)>
{
    constexpr static int value = T;
};

int main()
{
    std::cout << D<7>::value << std::endl;
}

Чтобы передать тип шаблона T шаблона D:

#include <iostream>

template <typename>
struct B
{
    constexpr static int T = 5;
};

template <int T>
struct D : B<decltype(T)>
{
    constexpr static int value = T;
};

int main()
{
    std::cout << D<7>::value << std::endl;
}