В вашем коде есть некоторые проблемы.
Прежде всего: вы определяете две разные Outer
структуры
template <bool B>
struct Outer
{ /* ... */ };
template <Inner<int> I>
struct Outer
{ /* ... */ };
И вы не можете.
Если вы хотите, вы можете объявить структуру Outer
и две специализации , но вы должны решить, какой тип аргумента шаблона Outer
должен получить.
Потому что, глядя на ваши desiderata,
int v = Outer<Inner<4>>::val;
int b = Outer<false>::val;
вы хотите передать ему тип в одном случае (Inner<4>
) и значение в другом случае. И вы не можете.
Вы должны решить, получит ли Outer
тип или значение. До C ++ 17, если получите значение, вы должны решить тип значения;начиная с C ++ 17, вы можете объявить Outer
как получающее значение универсального типа (auto
как тип значения).
Проблема: значение Inner<int>
не может бытьпараметр шаблона (но см. также ответ Майкла Кензеля, который показывает возможное решение C ++ 20, основанное на аргументах значений шаблона).
Таким образом, единственное решение, которое я вижу (до C ++ 20) - это объявление Outer
как получающий тип
template <typename>
struct Outer;
Затем вы можете определить Outer
специализацию для Inner
типов
template <int N>
struct Outer<Inner<N>>
{ enum { val = Inner<N>::val }; }; // or simply enum { val = N };
Для bool
значений, вы должны обернуть их вкласс;Я предлагаю (начиная с C ++ 11) использование стандартного класса std::integral_constant
и определение следующей Outer
специализации
template <bool B>
struct Outer<std::integral_constant<bool, B>>
{ enum { val = B }; };
Использование выглядит следующим образом:
int v = Outer<Inner<4>>::val;
int b = Outer<std::integral_constant<bool, false>>::val;
std::cout << v << std::endl;
std::cout << b << std::endl;
Вы также можете использовать std::false_type
, определяя b
int b = Outer<std::false_type>::val;
и, начиная с C ++ 17, также std::bool_constant
(сокращение для std::integral_constant
для bool
значений)
int b = Outer<std::bool_constant<false>>::val;