【问题标题】:Passing non-type parameter agument for templates为模板传递非类型参数参数
【发布时间】:2019-12-17 08:51:05
【问题描述】:

可能是愚蠢的问题:我正在尝试执行以下操作

template<unsigned int N>
class Foo{...}; // Define class Foo accordingly

int main(){
  for (unsigned int i = 0; i < 10; i++){
    Foo<i> f(3);
    f.show();
  }
  return 0;
}

正如您想象的那样,它不会编译,因为变量 i 不是 const。我知道这样做的原因是在非类型模板参数Foo&lt;i&gt; 中分配的值必须在编译时知道,因为这里不是这种情况,所以它真的不知道该怎么做。现在,我想知道是否有办法克服这个问题。当然,第一个想法是将unsigned int N 声明为Foo 类的成员变量。

所以问题:是否可以使用模板参数实现上述所需的行为,还是我必须将unsigned int N 声明为我的类的成员变量?

P.S.:我试图找到一个相关的问题,但我发现的问题与如何使用非类型模板参数有关,他们并没有完全回答这个问题。由于他们没有提到这是可能的,我认为这是不可能的......

编辑。

是否可以做到以下几点?

template<unsigned int N>
class Foo{...}; // Define class Foo accordingly

int main(){
  std::vector<Foo> v; // I know it's better with shared_ptr, etc.. but to get the idea..
  for (unsigned int i = 0; i < 10; i++){
    Foo<i> f(3);
    f.show();
    v.push_back( f );
  }
  return 0;
}

【问题讨论】:

标签: c++ templates


【解决方案1】:

我们的语言没有for constexpr,所以你不能直接做。您必须以某种方式模拟编译时 for 循环。有几种选择。

  1. 使用std::integer_sequence (C++14) 和int... 包:

    template<int i>
    void foo() {
        Foo<i> f(3);
        f.show();
    }
    
    template<int... is>
    void foo(std::integer_sequence<int, is...>) {
       (foo<is>(), ...);  // expands into foo<0>(), foo<1>(), ..., foo<9>()
    }
    
    foo(std::make_integer_sequence<unsigned int, 10>{});
    
  2. 使用递归和if constexpr (C++17) 模拟for 循环:

    template<unsigned int i>
    void foo()
    {
        Foo<i> f(3);
        f.show();
    
        if constexpr (i + 1 < 10)
            foo<i + 1>();
    }
    
    foo<0>();
    
  3. 使用std::integral_constant (C++11) 和函数重载:

    void foo(std::integral_constant<unsigned int, 10>) {}
    
    template<unsigned int i>
    void foo(std::integral_constant<unsigned int, i>) {
        Foo<i> f(3);
        f.show();
        foo(std::integral_constant<unsigned int, i + 1>{});
    }
    
    foo(std::integral_constant<unsigned int, 0>{});
    

Foo&lt;i&gt;Foo&lt;j&gt; 是不同的 ij 的不同类型。您不能将不同的类型放入std::vector。如果is 在编译时已知,您可以创建std::tupleFoo&lt;i&gt;s。但这仍然会使用一些模板技巧。

【讨论】:

  • 嗯。这似乎相当复杂。是否可以将 Foo 类的每个实例存储在容器内(std::vector)?因为您的解决方案似乎只是调用函数 show resp。 i的不同值的构造函数,这是可以理解的,因为我没有另外说明。
  • @ro_go, Foo&lt;i&gt;s 是不同is 的不同类型。您不能在 std::vector 中存储不同的类型。
  • 好吧,我应该猜到你不能把不同的类型放入std::vector。使用您的第一个建议,我如何从序列中获取单个元素 (foo(b), ...)?
  • (foo, ...) 是一系列函数调用。如果您想将Foo 放入容器中以便以后访问它们,可以使用std::tuple
  • 那么,我想使用成员声明更容易更直接?有没有回归?
猜你喜欢
  • 2019-04-24
  • 2016-10-20
  • 2017-03-18
  • 1970-01-01
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
相关资源
最近更新 更多