首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >模板类上的部分专门化成员函数

模板类上的部分专门化成员函数
EN

Stack Overflow用户
提问于 2022-08-29 19:02:36
回答 3查看 63关注 0票数 0

我有一些模板类,我需要为主类实现一个专门的成员函数。例如,如果我们有一个模板类Parent和其他两个模板类BoyGirl。我想为男孩和女孩实现一个专门的会员功能。女孩的成员函数还有一个论点。

男孩和女孩本身也是模板类,所以如何在这段代码中定义TT?

代码语言:javascript
运行
复制
template< typename TT >
class Child
{
    TT age;
};

template< typename TT >
class Boy< TT > : public Child< TT > 
{ ... };

class Girl< TT > : public Child< TT >
{ ... };

template<typename T>
class Parent {
private:
    std::vector< T > children;
//public:
//  void ProcessChild() {
//  }
};

template<> void Parent < Boy< TT > >::ProcessChild( TT age ) { // ??
  // implementation for boys
}

template<> void Parent< Girl< TT > >::ProcessChild( TT age, std::string name ) { // ??
  // implementation for girls
}

在这种情况下,T将是男孩或女孩,TT将是int或double。

我想要两个成员函数专门为ProcessChild,一个男孩和一个女孩。我似乎无法为我的代码找到适当的语法,也找不到任何其他示例,其中内部类也是一个模板类。其他示例包括对原语类型的专门化,如intdouble

我也在尝试这样的方法:

代码语言:javascript
运行
复制
template<>
template< class U >
class Parent < Girl< U > >
{
public:
    template< class TT >
    void ProcessChild( TT age, std::string name )
    {
         //...
    }
};

这里显示的所有代码都不是编译的。这是我遇到的错误之一:error: invalid use of incomplete type 'class Parent<Girl<U> >

额外:我的问题是扩展从这之前的职位。不过,我对这个例子做了相当多的修改。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-08-29 19:21:07

如果您想完全专门化该函数,那么可以显式实例化该函数以创建专门化,但在本例中这是行不通的,因为您不能部分地专门化函数模板。

在这种情况下,您最好的选择可能是将非专门化的功能提取到基类中。然后,您可以部分地专门化Parent<Boy<TT>>Parent<Girl<TT>>,并让它们都从基类派生出来:

代码语言:javascript
运行
复制
template <typename T>
class ParentBase {
protected:
    std::vector<T> children;
};

template <typename T>
class Parent;

template <typename TT>
class Parent<Boy<TT>> : ParentBase<Boy<TT>> {
public:
    void processChild(TT age) {
      // ...
    }
};

template <typename TT>
class Parent<Girl<TT>> : ParentBase<Girl<TT>> {
public:
    void processChild(TT age, std::string name) {
      // ...
    }
};

演示

票数 1
EN

Stack Overflow用户

发布于 2022-08-29 19:44:05

我会简化你的例子。

代码语言:javascript
运行
复制
template <typename> struct Foo { void foo() {}; };

你可以拥有这个:

代码语言:javascript
运行
复制
template <> void Foo<int>::foo() {}
template <> void Foo<double>::foo() {}
template <> void Foo<std::vector<int>>::foo() 

那将是类模板成员函数的显式特性

但你不能这样:

代码语言:javascript
运行
复制
template <> void Foo<std::vector<K>>::foo() {}

因为在任何地方都没有定义K。这K是什么意思?它应该在哪里定义?如果你想专门研究任何类型的向量,那么K应该是一个模板参数。哪里?

最明显的选择是

代码语言:javascript
运行
复制
template <typename K> void Foo<std::vector<K>>::foo() {}

但是不,显式的专门化语法不允许这样做。

等等,这不是Foo::foo的部分专长吗?不,函数模板没有部分的专门化,只有类模板。所以这里也没有运气。

您可以部分专攻Foo

代码语言:javascript
运行
复制
template <typename K> struct Foo<std::vector<K>> { void foo(); };

然后定义

代码语言:javascript
运行
复制
template <typename K> void Foo<std::vector<K>>::foo() {}

不再是无效的,但它也不再是专门化的了。这是Foo<std::vector<K>>成员的一个正常的越界定义,这是Foo的部分专门化.

票数 1
EN

Stack Overflow用户

发布于 2022-08-30 18:59:15

最后,我意识到我只能使用特定的参数对函数进行简单的重载,并使用函数声明中所需的类。值得注意的是,我在这里担心的是只正确地封装成员函数。例如,当父母在模板参数上有Boy时,不允许用户用两个参数调用ProcessChild。

这就是我所做的,它在假设时无法编译,而在假定时成功编译:

代码语言:javascript
运行
复制
template< typename TT >
class Child
{
    TT age;
};

template< typename TT >
class Boy< TT > : public Child< TT > 
{ ... };

class Girl< TT > : public Child< TT >
{ ... };

template<typename T>
class Parent {
private:
    std::vector< T > children;
public:
template< TT > void Parent < Boy< TT > >::ProcessChild( TT age ) { 
    addChild( *( new Boy< TT >( age ) ) );
}

template<> void Parent< Girl< TT > >::ProcessChild( TT age, std::string name ) { 
  addChild( *( new Girl< TT >( age, name ) ) );
}
};

在我的特定情况下,我实际上不必使用模板函数专门化。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73533521

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档