使用“std::function”(如语法)时,使用抽象类作为模板参数

Use abstract class as template argument when using `std::function` like syntax

本文关键字:抽象类 参数 function std 使用 语法      更新时间:2023-10-16

假设我有一个定义模板参数的类,如std::function语法。

// Class that accept template arguments like std::function
template< class T >
class abstraction;
template< class TAbstract, class ...TDeriveds >
class abstraction< TAbstract(TDeriveds...) >
{
public:
    using abstract_component_t = TAbstract;
    abstraction()
    {
        int i = 0;
    }
};
// Abstract base class
class base
{
public:
    virtual void func() = 0;
};
// Derived class
class derived : public base
{
public:
    void func() override
    {
    }
};

当我使用抽象类作为此类的模板参数(abstraction<base(derived)>)时,我收到以下错误:

VC++ 2015.3 error: C2259: 'base': cannot instantiate abstract class
GCC 4.9.2 error: invalid abstract return type 'base'

我想知道这是编译器中的错误还是禁止使用此语法的抽象类型?

链接到示例源。

模板参数TAbstract(TDeriveds...)是一种函数类型,它声明一个函数将TDeriveds...作为参数并按值返回TAbstract。按值返回时,必须可以实例化值类型的对象。抽象类的对象不能实例化,即按值返回它们是非法的(将它们作为参数也是如此)。相关条款为10.4 [类摘要] 第3段:

抽象类不得用作参数类型、函数返回类型或显式转换的类型。

但是,您可以通过引用返回抽象基类:

 template< class TAbstract, class ...TDeriveds >
 class abstraction< TAbstract&(TDeriveds...) >
 // ...

可悲的是,这意味着该类的用户在使用类时需要提及&

实际上,使用 TAbstract& (或指针类型)作为类的类型参数将解决问题。

问题是微不足道的:你不能返回抽象类的实例。相反,您可以返回 TAbstract 类型的引用或指针。