наследование элемента шаблона с использованием - PullRequest
2 голосов
/ 31 мая 2019

Следующие классы реализуют CRTP. Я хотел бы, чтобы класс Derived использовал конструктор, предоставленный Base, поэтому я пишу using. Тем не менее, я получаю сообщение об ошибке «могу наследовать конструктор только от прямой базы». Эквивалентно для переменной-члена x.


template<template<typename, size_t> typename G, typename F, size_t U>
struct Base
{
    double x;
    Base(double x) : x{ x } {}
    double gimme_x()
    {
        return (*static_cast<G<F, U>*>(this)).gimme_x();
    }
};

template<typename F, size_t U>
struct Derived : Base<Derived, double, U>
{
    using Base<Derived, double, U>::Base;
    using Base<Derived, double, U>::x;

    double gimme_x()
    {
        return x + 1.8;
    }
};

Эту проблему можно решить, изменив реализацию шаблона-шаблона Base на использование только обычного шаблона.


template<typename G, typename F, size_t U>
struct Base
{
    double x;
    Base(double x) : x{ x } {}
    double gimme_x()
    {
        return (*static_cast<G*>(this)).gimme_x();
    }
};

template<typename F, size_t U>
struct Derived : Base<Derived<F, U>, double, U>
{
    using Base<Derived<F, U>, double, U>::Base;
    using Base<Derived<F, U>, double, U>::x;

    double gimme_x()
    {
        return x + 1.8;
    }
};

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

1 Ответ

1 голос
/ 31 мая 2019

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

template<typename F, size_t U>
struct Derived : Base<Derived, double, U>
{
    using Base<::Derived, double, U>::Base;
    using Base<::Derived, double, U>::x;

    double gimme_x()
    {
        return x + 1.8;
    }
};

Демо

Код правильно компилируется с обоими gcc / clang Демо .

Это ошибка msvc, как

В следующих случаях имя введенного класса обрабатывается как имя шаблона самого шаблона класса:

  • сопровождается <</li>
  • используется в качестве аргумента шаблона, соответствующего параметру шаблона
  • это последний идентификатор в разработанном спецификаторе класса объявления шаблона класса друга.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...