c++ 当两个类型相等时,如何为泛型类上的泛型方法添加模板专用化?

zbq4xfa0  于 2023-01-15  发布在  其他
关注(0)|答案(2)|浏览(114)

我试图添加一个方法和类的泛型类型一致的专门化,但是我还不能准确地弄清楚如何指定模板示例化(如果可能的话)。
我最好的猜测是类似下面的代码(尽管它显然没有编译):

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;
}
oxf4rvwz

oxf4rvwz1#

正如在注解中所讨论的,使用模板专门化是不可能做到这一点的,但是,使用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为true时才会返回有效类型。因此,当MethodTClassT为相同类型时,模板替换会失败,但非模板重载不会失败。在SFINAE下,模板替换失败是可以的。

e1xvtsh3

e1xvtsh32#

通常在考虑函数模板专用化时,重载可以处理它:

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>)
{
}

相关问题