为模板参数包添加别名

aliassing a template parameter pack

本文关键字:添加 别名 包添加 参数      更新时间:2023-10-16

我想为参数包使用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);
}

有关如何访问CallerStructure方法接口的Base的可变参数模板的任何提示?

必需的编译器资源管理器链接

不能为可变参数模板参数添加别名。您可以将它们包装在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...);
}
};