создание псевдонима для пакета параметров шаблона - PullRequest
1 голос
/ 17 июня 2020

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

template <typename FirstArg, typename ... OtherArgs>
struct Base {
    using UsableFirstArg = FirstArg;
// this would be needed later
//    using UsableOtherArgs... = OtherArgs...;
    virtual OtherClass method(OtherArgs... a) = 0
};

template <typename DerivedOfBaseInstantiation>
struct CallerStructure {
// to be used here
//    OtherClass unknownCall(typename DerivedOfBaseInstantiation::UsableOtherArgs... args) {
//        DerivedOfBaseInstantiation instance;
//        return instance.method(args...);
//    }
}

Во время записи кода CallerStructure аргументы unknownCall неизвестны и определяются путем создания экземпляра CallerStructure, где DerivedOfBaseInstantiation - это тип, производный от Base. В более полном примере это будет выглядеть так:

class OtherClass {
};

template <typename FirstArg, typename ... OtherArgs>
struct Base {
    using UsableFirstArg = FirstArg;
    using UsableOtherArgs... = OtherArgs...;

    virtual OtherClass method(OtherArgs... a) = 0;

};

struct Derived_df : Base<int, double, float> {
    OtherClass someMethod(Base::UsableFirstArg);  // int
    OtherClass method(double, float) override ;
};



template <typename DerivedOfBaseInstantiation>
struct CallerStructure {
    OtherClass knownCall(typename DerivedOfBaseInstantiation::UsableFirstArg a) {
        DerivedOfBaseInstantiation instance;
        return instance.someMethod(a);
    }
    OtherClass unknownCall(typename DerivedOfBaseInstantiation::UsableOtherArgs... args) {
        DerivedOfBaseInstantiation instance;
        return instance.method(args...);
    }
};


void instantiations() {
    CallerStructure<Derived_df> c;
    [[maybe_unused]] auto a = c.knownCall(42);
    [[maybe_unused]]  auto b = c.unknownCall(23., 11.f);
}

Любые подсказки о том, как получить доступ к вариативным c шаблонам Base для интерфейса метода в CallerStructure?

обязательная ссылка на компилятор-проводник

1 Ответ

1 голос
/ 17 июня 2020

Вы не можете использовать псевдоним вариативного аргумента c шаблона. Вы можете обернуть их в std::tuple:

template <typename FirstArg, typename ... OtherArgs>
struct Base {
    using UsableFirstArg = FirstArg;
    using UsableOtherArgs = std::tuple<OtherArgs...>;

    virtual OtherClass method(OtherArgs... a) = 0;
};

Для распаковки нужны помощники:

template <typename DerivedOfBaseInstantiation,
          typename = typename DerivedOfBaseInstantiation::UsableOtherArgs>
struct CallerStructure;

template <typename DerivedOfBaseInstantiation, typename ... OtherArgs>
struct CallerStructure<DerivedOfBaseInstantiation, std::tuple<OthersArgs...>> {
    OtherClass knownCall(typename DerivedOfBaseInstantiation::UsableFirstArg a) {
        DerivedOfBaseInstantiation instance;
        return instance.someMethod(a);
    }
    OtherClass unknownCall(OtherArgs... args) {
        DerivedOfBaseInstantiation instance;
        return instance.method(args...);
    }
};
...