подкласс в качестве аргумента шаблона шаблона базового класса шаблона, который, в свою очередь, является параметром функции подкласса - PullRequest
2 голосов
/ 17 мая 2019

Следующий код

template<template<typename, typename> class T, typename EKeyType, typename EValueType>
class Baseclass
{
};

template<typename EKeyType, typename EValueType>
class Derived : public Baseclass<Derived, EKeyType, EValueType>
{
public:
    void foo(const Baseclass<Derived, EKeyType, EValueType>& param){}
};

приводит к следующим ошибкам компиляции:

MSVC 14: error C3200: 'Derived<EKeyType,EValueType>': invalid template argument for template parameter 'T', expected a class template
clang 3.0.0: error: template argument for template template parameter must be a class template.

Однако Derived - это шаблон класса.

Все отлично компилируется, когда я меняю код на следующее:

template<template<typename, typename> class T, typename EKeyType, typename EValueType>
class Baseclass
{
};

template<typename EKeyType, typename EValueType> class Derived;

template<typename EKeyType, typename EValueType>
class Derived2 : public Baseclass<Derived, EKeyType, EValueType>
{
public:
    void foo(const Baseclass<Derived, EKeyType, EValueType>& param){}
};

, что указывает на то, что сообщение об ошибке вводит в заблуждение.

Что не так с первым кодом?

Как получить подкласс шаблона, наследуемый от базового класса шаблона, при этом подкласс является аргументом шаблона шаблона базового класса, а также иметь функцию-член в подклассе, которая принимает ссылку на этот базовый класс в качестве параметра?

1 Ответ

3 голосов
/ 17 мая 2019

Первый фрагмент принят GCC и Clang. Смотрите здесь .

Кажется, я помню, что в MSVC есть ошибка, в которой Derived ссылается на имя введенного класса, а не на имя шаблона. Однако в стандарте совершенно ясно, что когда имя включающего класса используется в качестве аргумента параметра шаблона, его следует интерпретировать как шаблон ( [temp.local] / 1 ), поэтому ваш код в порядке.

Похоже, что старая версия Clang, которую вы используете, может иметь ту же ошибку.

В качестве обходного пути вы можете написать ::Derived, чтобы заставить его найти имя шаблона, а не имя внедренного класса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...