2017-01-08 8 views
0

Предположим, у меня есть класс, который определяет аргументы шаблона, такие как std::function синтаксис.Использовать абстрактный класс в качестве аргумента шаблона при использовании синтаксиса типа `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' 

я хочу знать, это ошибка в компиляторах или это запрещено использовать абстрактные типы с этим синтаксисом?

Link к образцу источника.

+0

Возможно, здесь будет полный источник, это яснее, и это не так уж много кода. Приходит вплоть до написания требующий базового экземпляра, поскольку это тип значения. Я не говорю «standardeze» достаточно хорошо, но, вероятно, кто-то другой может придумать точное стандартное правило, запрещающее это. – stijn

+0

Интересно, что он отлично компилируется с clang 3.9. –

ответ

3

Аргумент шаблона TAbstract(TDeriveds...) - это тип функции, объявляющий функцию, принимающую TDeriveds... как аргументы и возвращающую значение TAbstract по значению. При возврате по значению необходимо, чтобы объекты типа значения могли быть созданы. Объекты абстрактного класса не могут быть созданы, т. Е. Возвращать их по значению незаконно (как принимает их как параметры). Соответствующим пунктом является 10.4 [класс.абстракт], пункт 3:

Относительный класс не должен использоваться в качестве типа параметра, как возвращаемый тип функции, или как тип явного преобразования. ...

Вы можете, однако, вернуться абстрактные базовые классы по ссылке:

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

К сожалению, это означает, что пользователи класса необходимо упомянуть & при использовании класса.

+0

Но нет никакого типа возврата. Тип 'base' использовался в качестве аргумента шаблона для другого типа. Этот синтаксис является только «синтаксисом сахара» для нормального использования: 'абстракция ' – MRB

+0

@MRB: объявление функции в специализации шаблона * четко * использует 'TAbstract' (который заменяется на' base') как return type - это то, где это незаконно. –

+0

Вы говорите, что используя синтаксис '', я использую объявление функции? Итак, как он компилируется в «clang»? – MRB

1

На самом деле, с помощью TAbstract & (или типа указателя) в качестве аргумента типа для вашего класса будет решена проблема.

Проблема тривиальна: вы не можете вернуть экземпляр абстрактного класса. Вместо этого вы можете вернуть ссылку или указатель типа TAbstract.