шаблонный класс, обертывающий произвольный тип / не типовой шаблонный класс - PullRequest
0 голосов
/ 27 июня 2018

Предположим, у меня есть шаблонный класс base и класс wrapper, который содержит экземпляр класса base. Я хотел бы определить класс wrapper так, чтобы он зависел от пакета параметров шаблона, который просто «передается» в экземпляр элемента base.

Например, рассмотрим следующий код, который отлично работает.

#include <iostream>

template <int i, int j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << j << std::endl;
  }
};

template <int... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<2, 3> x;
  return 0;
}

Заранее зная, что все параметры шаблона base равны int, я использую template <int...T> в объявлении wrapper. Это обеспечивает ограниченную гибкость, например, я мог бы определить некоторые значения по умолчанию для параметров шаблона base, без изменения wrapper.

Однако, если base зависит от произвольного списка типовых и нетиповых параметров шаблона, как я могу передать параметры шаблона wrapper в base?

Например, если я знаю, что все параметры шаблона base могут быть неявно преобразованы в int (без потерь!), Я мог бы определить wrapper как в следующей программе

#include <iostream>

template <int i, bool j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << (j ? "true" : "false") << std::endl;
  }
};

template <int... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<2, true> x;
  return 0;
}

Но если base зависит в то же время от типовых и нетиповых параметров шаблона, как в следующей программе, очевидно, невозможно просто передать параметры шаблона wrapper в base:

#include <iostream>

template <class U, int i, int j>
struct base {
  base()
  {
    std::cout << "i is " << i;
    std::cout << " j is " << j << std::endl;
  }
};

template <class... T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<int, 2, 3> x; // Error!
  return 0;
}

Эта программа не компилируется, потому что компилятор ожидает типы для wrapper.

Есть ли способ написать класс wrapper, который "передает" параметры своего шаблона элементу типа base, , независимо от того, что они ?

Идея состоит в том, чтобы иметь общий код для wrapper, который не нужно изменять, если, скажем, изменяется шаблонная подпись base.

1 Ответ

0 голосов
/ 27 июня 2018

Есть решение Вашей проблемы. Это не очень элегантно и требует особого подхода, но работает в случаях, которые вы хотите:

template <class U, class i, class j>
struct base {
  base()
  {
    std::cout << "i is " << i::value;
    std::cout << " j is " << j::value << std::endl;
  }
};

template <class ...T>
struct wrapper {
  base<T...> a;
};

int main()
{
  wrapper<int, std::integral_constant<int, 2>, std::integral_constant<int, 3>> x; //no error now!
  return 0;
}

С C ++ 17 это может быть менее многословно:

template<auto val>
using value_wrapper = std::integral_constant<decltype(val), val>;

int main()
{
  wrapper<int, value_wrapper<2>, value_wrapper<3>> x; //no error now!
  return 0;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...