Инициализация конструктора шаблона с переменной типа size_t - PullRequest
0 голосов
/ 13 июня 2018

У меня есть класс с конструктором шаблона:

class x
{
  public:

    template<std::size_t N>
    x(int matrix[N][N])
     {
        A<N> ob(matrix);
     }
};

в основной функции:

int main()
{
   size_t s;
   cin >> s;
   int m[s][s];

   x ob(m); // error
}

ошибка:

ошибка:нет соответствующей функции для вызова 'x::x(int [s][s])' |

Я хочу создать массив, размер которого указан пользователем, и передать его x::x(), который использует его для создания объекта класса шаблона.A определяется как:

template<size_t N>
class A
{
 ...
};

Любые решения для этого, я хочу, чтобы N вводился во время выполнения и передавался как аргумент шаблона.На самом деле я хотел передать его непосредственно A, но он выдает ошибку: non-const template arguement, поэтому я подумал о создании A в другом классе, но ошибка тоже есть.

Я использую кодовые блоки 16.01.

Ответы [ 2 ]

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

Я хочу, чтобы N вводился во время выполнения и передавал его в качестве аргумента шаблона.

Краткий ответ: это невозможно.

Длинный ответ: как объяснено с помощью RСаху, параметр шаблона должен быть известен во время компиляции, поэтому для него невозможно использовать значение времени выполнения.

В вашем конкретном случае, если class x не зависит от размера s, но используйтетолько в конструкторе (?) ... если у вас ограниченное количество принятых s значений (от 1 до 5, например), вы можете использовать switch следующим образом

#include <memory>
#include <iostream>

template <std::size_t N>
struct foo
 {
   foo (int[N][N])
    { std::cout << "-- foo " << N << std::endl; }
 };

struct bar
 {
   template <std::size_t N>
   bar (int matrix[N][N])
    { foo<N> ob(matrix); }
 };

int main ()
 { 
   std::unique_ptr<bar>  pOb;

   std::size_t s;

   std::cin >> s;

   switch ( s )
    {
      case 1: int m1[1][1]; pOb.reset(new bar{m1}); break;
      case 2: int m2[2][2]; pOb.reset(new bar{m2}); break;
      case 3: int m3[3][3]; pOb.reset(new bar{m3}); break;
      case 4: int m4[4][4]; pOb.reset(new bar{m4}); break;
      case 5: int m5[5][5]; pOb.reset(new bar{m5}); break;
      default: /* throw some exception ? */ break;   
    }

   // do something with pOb
 }

ThisКстати, в отдельных случаях размер матрицы известен как время компиляции, поэтому вы передаете значение времени компиляции в аргумент шаблона.

Но, как вы можете видеть, вы должны написать case для каждого принятого значения s, так что вы можете подумать, что использовать решение, подобное этому, это только количество принятых значений sочень ограничен.

Очевидно, что если содержимое case велико, вы можете разработать для него функцию шаблона.

Например, вы можете разработать baz() функцииследующим образом

template <std::size_t N>
std::unique_ptr<bar> baz ()
 {
   int m[N][N]; 

   /* do something for m */

   return std::unique_ptr<bar>(new bar{m});
 }

, поэтому switch становятся

switch ( s )
 {
   case 1: pOb = baz<1>(); break;
   case 2: pOb = baz<2>(); break;
   case 3: pOb = baz<3>(); break;
   case 4: pOb = baz<4>(); break;
   case 5: pOb = baz<5>(); break;
   default: /* throw some exception ? */ break;   
 }
0 голосов
/ 13 июня 2018

Компилятор сможет использовать

template<std::size_t N>
x(int matrix[N][N]) { ... }

, только если во время компиляции известно N.

Когда вы используете

size_t s;
std::cin >> s;
int m[s][s];

x ob(m); // error

, то естьне правда.Значение s может быть известно только во время выполнения.Компилятор справедливо сообщает об этом как об ошибке.

Вы можете устранить ошибку компилятора, изменив объявление конструктора или изменив способ его использования.Из вашего поста не ясно, что вы пытаетесь сделать с аргументом конструктора.Следовательно, я не могу предложить конкретное решение.

Я хочу, чтобы N вводился во время выполнения и передавался как аргумент шаблона.

Этоэто невозможно.Все параметры шаблона должны быть известны во время компиляции.Вам придется изменить свой дизайн, чтобы вы могли использовать тип контейнера, размер которого можно определить во время выполнения, например std::vector.Вы можете использовать std::vector<std::vector<int>> для эмуляции 2D-массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...