【问题标题】:How to properly specify a recursive template class member function?如何正确指定递归模板类成员函数?
【发布时间】:2021-12-27 03:52:32
【问题描述】:

我想解压可变参数模板参数包。由于该函数需要访问对象的私有成员,因此我决定将其编写为成员函数。据我了解,根据标准,必须在与封闭类相同的命名空间中指定模板函数,我试图将声明和定义分开。结果我只收到了查找错误。

下面是我正在尝试做的一个简短的娱乐:

class Container{
private: 

    //My first try
    template<typename... Ts>
    void foo();

    //Second try
    template<> foo();
    template<typename T, typename... Ts>
    void foo();
}

template<> void Container:foo(){}

template<typename T, typename... Ts>
void Container::foo(){
    foo<Ts...>();
}

我应该写什么而不是注释部分,或者我在尝试这个时是否存在更普遍的错误?

我已经看过像recursive variadic template to print out the contents of a parameter pack 这样的问题,但没有一个使用成员函数,所以遗憾的是它并没有真正帮助。

此外,在参数列表为空的情况下,这应该什么都不做。这就是为什么以下方法不起作用的原因。

template<typename T, typename... Ts>
void foo(){
    if constexpr (sizeof...(Ts)){
        foo<Ts...>();
    }
}

关于错误信息:

对于尝试 1 -

Container::foo() 不匹配任何模板声明

对于尝试 2 -

非命名空间范围类容器中的显式特化

【问题讨论】:

    标签: c++ templates c++17


    【解决方案1】:

    在 C++20 中,您可以使用模板 lambda 来提取第一个模板参数,如下所示:

    class Container {
     private: 
      template<typename... Ts>
      void foo();
    };
    
    template<typename... Ts>
    void Container::foo() { 
      if constexpr (sizeof...(Ts))
        [this]<typename /*First*/, typename... Rest> {
          foo<Rest...>();
        }.template operator()<Ts...>();
    }
    

    Demo.

    但与使用递归相比,折叠表达式(已在其他答案中给出)在您的情况下似乎是一种更有效的方法。

    【讨论】:

      【解决方案2】:

      您的第一次尝试没有成功,因为声明 template&lt;typename... Ts&gt; void foo(); 必须与看起来相同的声明匹配,而不是 template&lt;typename T, typename... Ts&gt; void foo() { // ...,后者具有不同的模板参数。

      在 C++17 中,使用 fold expressions 为参数包中的每一件事“做某事”非常简单:

      class Container {
      private:
          template<typename... Ts>
          void foo();
      };
      
      template<typename... Ts>
      void Container::foo() {
          // Fold over comma which calls and discards the result of a lambda
          (([&]{
              // Use `Ts` here. For example:
              std::cout << typeid(Ts).name() << '\n';
          }()), ...);
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-25
        • 2010-09-13
        • 1970-01-01
        • 1970-01-01
        • 2022-01-10
        相关资源
        最近更新 更多