当前位置: 首页 > 知识库问答 >
问题:

如何为特定类型专门化模板类方法?

白哲茂
2023-03-14

我有这样的代码:

class Bar {
 public:
  void print() {
    std::cout << "bar\n";
  }
};

template<typename T>
class Foo {
 public:
  template <typename std::enable_if<std::is_base_of<T,Bar>::value,T>::type>
  void print() {
    t.print();
  }

 template <typename>
  void print() {
    std::cout << t << std::endl;
  }
 private:
  T t;
};

int main() {
//  Foo<int> foo1;
  Foo<Bar> foo2;
  foo2.print();
}

这段代码的目的是:如果T tBarBar的子类,则将foo.print()推导为ulualprint(){t.print ();},否则推导为ulualprint(){std::c

“非类型模板参数的类型不能为'typename std::enable_if::value,Bar。”

这段代码有什么问题?


共有3个答案

张和颂
2023-03-14

您应该在调用print()时添加模板参数,因为它本身就是一个模板方法。无论如何,你的设计太复杂了!

使用C 17变得非常简单,您只需要一个Foo

void print() {
  if constexpr(std::is_base_of_v<T,Bar>) // ignores `Foo<int>`
    t.print();
}

演示。

司寇旺
2023-03-14

由于您实际上对阉羊感兴趣,因此类型具有成员函数print或定义了运算符

随着即将推出的C20标准,我们得到了一些概念

namespace traits
{
template<typename T>
concept has_print_v = requires(T&& t) { t.print(); };

template<typename T>
concept has_ostream_op_v = requires(T&& t, std::ostream& os) { os << t; };
} // end of namespace traits

使用这样的概念:

template<typename T>
class Foo
{
public:
    void print()
    {
        if constexpr (traits::has_print_v<T>) { t.print(); }
        else if constexpr (traits::has_ostream_op_v<T>) { std::cout << t << "\n"; }
    }
private:
    T t;  
};

慕翰学
2023-03-14

>

  • 您应该将print()的重载设置为函数模板(以使SFINAE工作),否则非模板函数总是首选。

    您应该让print()获取自己的模板类型参数;类型检查不应该直接对类模板参数T执行,函数模板重载解析和SFINAE是对函数模板本身执行的,类模板不涉及。

    您可以将std::enable_if的部分移动到返回类型。

    您应该将指定的顺序更改为std::is_base_of(即std::is_base_of

    例如

    template <typename X = T>
    typename std::enable_if<std::is_base_of<Bar, X>::value>::type print() {
      t.print();
    }
    
    template <typename X = T>
    typename std::enable_if<!std::is_base_of<Bar, X>::value>::type print() {
      std::cout << t << std::endl;
    }
    

    居住

  •  类似资料:
    • 我有一个通用算法,需要访问其模板类型的特征。有一个特征类可以专门用于提供这些特征。 在我的类中使用此算法时,我想将其与类中定义的私有类型一起使用。 然而,专门化只能发生在或全局范围内,而我的类是不可访问的。 是否有可能以某种方式专门化具有私有类型的模板,至少在可访问此类型的范围内? 也许可以将这个专门化声明为一个类?

    • 还尝试在专门化的中进行模板方法专门化: 这一次它编译,但调用原始方法,即 解决方案

    • 关于下一个代码,我有一些问题: > 类专业化

    • 问题内容: 这是我的代码: 它运作良好。但是当我尝试添加这个 我遇到编译器错误:«int MyClass :: DoSomething()»的«>»令牌模板标识«DoSomething <0>»之前的无效显式专门化与任何模板声明都不匹配 我使用g ++ 4.6.1应该怎么做? 问题答案: 不幸的是,如果不对外部模板进行特殊化处理,就不能对作为类模板成员的模板进行特殊处理: C ++ 11 14.7

    • 问题内容: 我想知道在Java中专门化泛型类型的选项是什么,即在模板化类中具有对某些类型的特定替代的选项。 在我的情况下,我是一个泛型类(类型T),通常返回null,但是当T为String类型时返回“”(空字符串),而当其Integer类型时返回0(零),等等。 仅提供方法的特定于类型的重载会产生“方法不明确”错误: 例如: 是用特定类型将泛型类子类化的唯一选择(请参见以下示例中的StringBa

    • 也许我累了,但是我被这个简单的局部特化卡住了,它不起作用,因为指定模板参数: 将替换为,或没有帮助。那么这种专门化是否可能呢?