【问题标题】:template specialization with multiple template parameters具有多个模板参数的模板特化
【发布时间】:2011-10-04 04:36:13
【问题描述】:

说我有这个:

template<typename T, int X>
class foo 
{
public:
  void set(const T &t);
};

template<typename T, int X>
void foo::set<T, X>(const T &t)
{
  int s = X;
  // ...etc
}

我可以特化函数类型“T”但保留“X”作为模板参数吗?

class bar;

template<int X>
void foo::set<bar, X>(const bar &t)
{
  int s = X;
  // ...etc
}

这可能吗?

【问题讨论】:

  • void foo::set&lt;T, X&gt;(const T &amp;t) -> void foo&lt;T,X&gt;::set(const T &amp;t)

标签: c++ templates template-specialization


【解决方案1】:

一旦你掌握了窍门,这将非常容易

template<typename T, int X>
class foo 
{
private:
  template<typename, int> class params { };

public:
  void set(const T &t) {
    set(t, params<T, X>());
  }

private:
  template<typename T1, int X1>
  void set(const T1 &t, params<T1, X1>) {
     // ...
  }

  template<int X1>
  void set(const bar &t, params<bar, X1>) {
    // ...
  }
};

这是必要的,因为如果您明确专门化单个成员,则必须提供所有模板参数。你不能留下一些。

【讨论】:

  • 这是正确的,但我个人会避免这样的伎俩。它使代码不可读。 IMO 类的部分特化或类似的东西,具体取决于情况(例如,创建基类模板并部分特化它并在非特化派生类中实现(许多?)非特化函数)是更好的决定。
  • @Serge 部分专业化专攻整个班级。因此,如果他只希望单个功能的特殊行为是不合适的。创建基本模板会带来更多的噪音和不便(您将无法访问“foo”的成员,...)。如果您对上述问题有更清洁的解决方案,欢迎您发布。
  • “部分专业化全班专业化” - 是的。 “创建一个基本模板会产生更多的噪音和不便” - 通常这不是不便 - 使架构保持一致只是一项额外的小工作。如果需要专门化,那么通常有一些关于这种情况的特殊逻辑可能值得单独的(基)类专门化。如果有很多公共成员对象,那么将它们(受保护)放在另一个类中作为两个父特化的基础是没有问题的(通常这背后有一个逻辑)。
  • 我知道这听起来很复杂,但如果一切都一致实现,那么它比重载技巧更具可读性。
  • @Serge 我不明白你为什么认为这两个重载是不可读的。 IMO,它们是最易读的解决方案。
【解决方案2】:

您可以考虑重写代码以使成员函数成为单独的模板:

template <int X> class foo
{
  template <typename T> void set(const T &);
  // ...
};

然后您可以为模板foo&lt;X&gt;::set 提供显式特化。

【讨论】:

    【解决方案3】:

    没有。这是不允许的。 class 成员函数必须完全专业化。例如,应该是,

    template<>
    void foo<bar, 5>::set(const bar &t)
    {          //^^^^
      int s = 5;
      // ...etc
    }
    

    【讨论】:

      【解决方案4】:

      您可以对整个班级进行部分专业化。在这种情况下,您可以针对类的每个特化为 set 函数提供不同的实现。

      【讨论】:

      • @MarkP,检查this 答案。
      猜你喜欢
      • 1970-01-01
      • 2011-06-10
      • 2018-06-25
      • 2022-01-21
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 2012-09-29
      • 2015-02-19
      相关资源
      最近更新 更多