【问题标题】:How do I add a template specialization when for a generic method on a generic class when the two types are equal?当两种类型相等时,如何为泛型类上的泛型方法添加模板专业化?
【发布时间】:2023-01-12 04:53:39
【问题描述】:

我正在尝试添加通用类型的方法和类一致的专门化,但我一直无法弄清楚如何指定模板实例化(如果可能的话)。

我最好的猜测是类似于以下内容(尽管它显然无法编译):

template<typename ClassT>
class Foo
{
public:
  ClassT x;

  template<typename MethodT>
  void Bar(MethodT arg)
  {
  }
};

template<typename T>
template<>
void Foo<T>::Bar(T arg)
{
  x = arg;
}

【问题讨论】:

  • 这必须是专业化还是常规超载?
  • 不幸的是,模板类必须在它的任何模板方法被特化之前被特化。
  • 克里斯,如果重载有效,那就太好了,但我认为不枚举每种类型是不可能的,对吗?

标签: c++ templates template-meta-programming


【解决方案1】:

正如在 cmets 中所讨论的,不可能通过模板专业化来做到这一点。然而,类似的事情可以通过使用 std::enable_if_t 和

template<typename ClassT>
class Foo
{
public:
  ClassT x;

  template<typename MethodT,
    typename = std::enable_if_t<!std::is_same<ClassT, MethodT>::value>>
  void Bar(MethodT arg)
  {
  }

  void Bar(ClassT arg)
  {
    x = arg;
  }
};

std::enable_if_t 只会在输入类型 arg 为真时返回有效类型。因此,当MethodT和ClassT为同一类型时,模板替换会失败,但非模板重载不会失败。模板替换失败在SFINAE下是可以的。

【讨论】:

    【解决方案2】:

    正如考虑函数模板特化时通常的情况一样,重载可以处理它:

    template<typename MethodT>
    void Bar(MethodT arg)
    {
    }
    
    void Bar(ClassT arg)
    {
      x = arg;
    }
    

    当您致电Bar 时,其中一位候选者将是函数模板专业化,而另一位则不会。将类模板视为在实例化时在可能的情况下消除真实的、具体的成员函数。在重载决议中有一条规则很晚,如果它与那一点有关,则更喜欢不是函数模板特化的规则。

    您最终得到的是当类型中存在“完全匹配”时调用的第二个重载(这允许在顶级const 中存在差异)。如果完全匹配太窄,您可以限制第一个重载以扩大第二个重载:

    // Allow the other overload to win in cases like Foo<int>{}.Bar(0.0).
    // std::enable_if works as well before C++20.
    template<typename MethodT>
    void Bar(MethodT arg) requires (not std::convertible_to<MethodT, ClassT>)
    {
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-16
      • 1970-01-01
      相关资源
      最近更新 更多