简体   繁体   English

让模板的部分专业化与通用实例共享成员函数

[英]Let template partial specializations share member functions with general instantiations

Suppose I have a class template Foo : 假设我有一个类模板Foo

template<typename T, typename U>
struct Foo {
    ~Foo() = default;

    // I want to reuse these methods for all instantiations of Foo
    void bar() {}
    void poi() {}
};

I want to specialize the destructor for any Foo<T, int> , but I want Foo<T, int> to share the other member functions with the general instantiations. 我想专门针对任何Foo<T, int>的析构函数,但我希望Foo<T, int>与常规实例共享其他成员函数。 But if I try to do: 但是,如果我尝试这样做:

template<typename T>
Foo<T, int>::~Foo()
{}

outside the class, it doesn't compile, the error being "invalid use of incomplete type struct Foo<T, int> ". 在类外部,它不会编译,错误是“无效使用不完整类型struct Foo<T, int> ”。 What does this error mean, and how can I achieve what I'm trying to do? 此错误是什么意思,我如何实现自己的目标?

It is not possible to partially specialise a (non-templated) member function. 不可能部分专门化(非模板化的)成员函数。 You need to specialise the whole class. 您需要对整个班级进行专业培训。

One way to do what you want is to inherit the common functions. 一种实现所需功能的方法是继承通用功能。

template<typename T, typename U> struct MemberProvider
{
      ~MemberProvider() = default;

      void bar() {};
      void poi() {};
};


template<typename T, typename U>
struct Foo : public MemberProvider<T, U>
{
    ~Foo() = default;

// Optionally, you can still do this.
//    However, note that these HIDE the inherited functions

    void bar() {};
    void poi() {};
};

template<typename T> struct Foo<T, int> : public MemberProvider<T, int>
{
    ~Foo() {};
};

Note you will also need to include any members acted on by the common functions in the inherited class. 注意,您还需要在继承的类中包括所有由通用函数作用的成员。

However, I would suggest the above represents a code smell. 但是,我建议以上内容代表代码气味。 If I saw code like the above in a production environment, I'd be contemplating the presence of a design flaw. 如果在生产环境中看到上面的代码,我将考虑存在设计缺陷。 Bear in mind that, when destructing such a class, the most derived destructor is invoked before base class destructors. 请记住,在销毁此类时,将在基类销毁器之前调用最派生的销毁器。 MemberProvider is also not a polymorphic base. MemberProvider也不是多态基础。

You can explicitly specialize member functions of class templates, but you cannot partially specialize them - which is what you're trying to do. 您可以显式地专门化类模板的成员函数,但是不能部分地专门化它们-这是您要尝试的工作。

If you need to partially specialize the destructor in a way that keeps the generic version defaulted, you'll have to partially specialize the whole class template: 如果您需要以使通用版本保持默认状态的方式来部分化析构函数,则必须部分化整个类模板:

template <class T, class U>
struct FooCommon {
    ~FooCommon() = default;

    void bar() {}
    void poi() {}
};

template <class T, class U>
struct Foo : FooCommon<T, U> { };

template <class T>
struct Foo<T, int> : FooCommon<T, int> {
    ~Foo() {
        // special logic here
    }
};

If foo and poi do things that depend on the template parameters, then you could extract your specialised destructor behaviour into a separate class, eg, 如果foopoi行为取决于模板参数,则可以将专门的析构函数的行为提取到单独的类中,例如,

#include <iostream>

template <typename T, typename U>
struct Foo;

template <typename T, typename U>
struct FooDestructorTraits
{
    static void destroy(Foo<T, U> * ptr)
    {
        std::cout << "default" << std::endl;
    }
};

template <typename U>
struct FooDestructorTraits<int, U>
{
    static void destroy(Foo<int, U> * ptr)
    {
        std::cout << "special" << std::endl;
    }
};

template <typename T, typename U>
struct Foo 
{
    ~Foo() noexcept { FooDestructorTraits<T, U>::destroy(this); }

    void bar() {}
    void baz() {}
};

int main() {
    Foo<void, void> x;
    Foo<int, void> y;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM