推断可变参数函数模板时出错

时间:2013-11-18 17:44:04

标签: c++ templates variadic-templates

我对可变参数模板函数的类型推导有问题。这是我正在尝试做的事情:

我有一个模板类,可以作为分配器使用。为了选择合适的分配器,我需要一些关于类型参数的信息。信息收集在矢量中。

创建实际元数据的函数如下所示:

template<typename T> 
MetaData* create_meta() { 
    return new DefaultMetaData(); 
}

template<MyExampleType> 
MetaData* create_meta() { 
    return new MyExampleTypeMetaData(); 
}

template<MyOtherType> 
MetaData* create_meta() { 
    etc. 
}

收集元数据的功能现在看起来像这样:

template<typename T, typename... Args>
void fill_meta_data(std::vector<MetaData*> &meta) { 
    meta.push_back(create_meta<T>()); 
    fill_meta_data<Args...>(meta);
}

编辑:尝试清除问题:

我想像这样调用fill_meta_data函数:

fill_meta_data<MyExampleType, MyExampleType, MyOtherType>(meta_data_vector)

因此,meta_data_vector包含MyExampleType,MyExampleType和MyOtherType的元数据

我得到的错误是“模板参数扣除/替换失败:无法推断模板参数'T'”。

我认为当它试图推断出无参数版本的参数时会出现问题,但是,我只是无法弄清楚如何定义这个默认值(它应该返回的地方)。

我已经尝试template<>(无法识别),template<typename... Args>(编译器说有两个实现超过0个参数)。

也欢迎针对这个问题的不同解决方案:)

谢谢!

编辑:感谢@catscradle的链接: 这是一个对我有用的解决方案:

我必须添加模板

template<typename... Args>
typename std::enable_if<sizeof...(Args) == 0>::type
fill_meta_data(std::vector<MetaData*> &meta) {}

仅在Args参数的大小为零时启用。

谢谢大家!

1 个答案:

答案 0 :(得分:0)

您的代码中存在一些语法错误,但一旦排除它们就不会出现问题。

您的功能专长是错误的。而不是:

template<typename T> 
MetaData* create_meta() { 
    return new DefaultMetaData(); 
}

template<MyExampleType> 
MetaData* create_meta() { 
    return new MyExampleTypeMetaData(); 
}

尝试:

template<typename T> 
MetaData* create_meta() { 
    return new DefaultMetaData(); 
}

template <>
MetaData* create_meta<MyExampleType>() { 
    return new MyExampleTypeMetaData(); 
}

另一个问题是你的递归没有最终功能。有些人发现提取递归很有帮助,因此更有意义。如果我们用某些类型绘制你的递归,我们可能会得到这个:

fill_meta_data<short, int, long> // T = short, Args... = int, long
fill_meta_data<int, long>        // T = int, Args... = long
fill_meta_data<long>             // T = long, Args... = 
fill_meta_data<>                 // T = ???, Args... =

你可以看到最后一步是未定义的,因为T没有意义,但需要输入。因此,要“关闭”递归模板函数,您只需要一个常规函数重载,而不需要任何参数:

void fill_meta_data(std::vector<MetaData*> &meta) { 
}

template<typename T, typename... Args>
void fill_meta_data(std::vector<MetaData*> &meta) { 
    meta.push_back(create_meta<T>()); 
    fill_meta_data<Args...>(meta);
}
相关问题