推导参数包中各类型模板参数,实现多Pass对象的Test类是否可行?
你的实现不可行,我来帮你修正并实现需求
首先得指出你当前代码的核心问题:你定义的Test模板参数是template <typename P1, typename P2> class... T,这意味着它期望接收**多个模板(比如Pass本身)**作为参数,而不是你想要的Pass类的实例对象。当你尝试用Pass<int, float>()这类实例去初始化Test时,编译器会直接报错,因为参数类型完全不匹配。
正确的实现思路
我们需要让Test模板接收一组Pass<P1, P2>类型的实例作为参数包,然后通过模板元编程提取每个Pass内部的P1和P2类型,以此来构建三个std::tuple。
完整代码实现
#include <tuple> #include <string> // 保留你原有的Pass模板 template <class T, class U> class Pass { }; // 辅助模板:用于提取Pass类型的两个模板参数 template <typename> struct PassTraits; template <typename P1, typename P2> struct PassTraits<Pass<P1, P2>> { using FirstType = P1; using SecondType = P2; }; // 最终的Test类模板 template <typename... PassInstances> class Test { // 预定义三个tuple的类型 using Tuple1 = std::tuple<PassInstances...>; using Tuple2 = std::tuple<typename PassTraits<PassInstances>::FirstType...>; using Tuple3 = std::tuple<typename PassTraits<PassInstances>::SecondType...>; public: // 构造函数:用传入的Pass实例初始化tuple1 Test(PassInstances... passes) : tuple1(std::make_tuple(std::move(passes)...)) {} // 三个公开的tuple成员 Tuple1 tuple1; Tuple2 tuple2; Tuple3 tuple3; }; // 测试实例化 int main() { Test t{ Pass<int, float>(), Pass<int, int>(), Pass<std::string, float>() }; // 此时: // t.tuple1 是 std::tuple<Pass<int,float>, Pass<int,int>, Pass<std::string,float>> // t.tuple2 是 std::tuple<int, int, std::string> // t.tuple3 是 std::tuple<float, int, float> return 0; }
代码解释
PassTraits辅助模板:专门用来从任意Pass<P1,P2>类型中提取出它的两个模板参数P1和P2,这是实现类型提取的核心。Test模板参数:改为typename... PassInstances,表示接收任意数量的Pass实例类型作为参数包。- tuple类型定义:通过
PassTraits依次提取每个PassInstances的FirstType和SecondType,分别构建出tuple2和tuple3的类型。 - 构造函数:使用
std::make_tuple和std::move高效初始化tuple1,避免不必要的拷贝。
这样修改后,你的实例化代码就能正常工作,完全满足你想要的生成三个tuple的需求。
内容的提问来源于stack exchange,提问作者Pavlo Muratov
相关产品推荐
相关产品推荐

