【问题标题】:Initializing a template constructor with a size_t type variable使用 size_t 类型变量初始化模板构造函数
【发布时间】:2018-11-23 05:41:07
【问题描述】:

我有一个类,带有模板构造函数:

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 argument,所以我想在另一个类中创建A,但是错误也在那里。

我正在使用代码块 16.01。

【问题讨论】:

  • size_t s; cin &gt;&gt; s; int m[s][s]; 不是 C++ 标准。数组的大小必须是编译时已知的值。
  • @max66 那么编译器如何允许它
  • template&lt;std::size_t N&gt; x(int matrix[N][N]) 调整为template&lt;std::size_t N&gt; x(int (*matrix)[N])
  • 如果您不要求严格遵守,一些编译器会接受非标准代码。如果使用 clang++ 或 g++ 编译,请尝试添加 -ansi -pedantic
  • @max66 你知道任何解决方案吗?我如何在运行时传递输入N 然后使用它。

标签: class c++11 templates size-t template-classes


【解决方案1】:

我希望在运行时输入 N 并将其作为模板参数传递。

简短的回答:这是不可能的。

长答案:正如 R Sahu 所解释的,模板参数必须在编译时已知,因此不可能为其使用运行时值。

在您的特定情况下,如果 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
 }

这样,在单个情况下,矩阵的大小是已知的编译时间,因此您将编译时间值传递给模板参数。

但是,正如您所看到的,您必须为每个接受的 s 值编写一个 case,因此您可以认为使用这样的解决方案只是接受的 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;   
 }

【讨论】:

    【解决方案2】:

    编译器可以使用

    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&lt;std::vector&lt;int&gt;&gt; 来模拟二维数组。

    【讨论】:

    • 我希望在运行时输入矩阵的大小,然后将此矩阵传递给构造函数,我该如何实现这一点。实际上这个 N 被构造函数中使用的另一个模板类所接受
    • 检查我已将其编辑为我真正想做的帖子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-23
    • 2020-05-11
    相关资源
    最近更新 更多