gpt4 book ai didi

c++ - 递归地扩展类和函数的可变参数模板

转载 作者:太空狗 更新时间:2023-10-29 21:01:33 25 4
gpt4 key购买 nike

所以我一直在尝试更多地了解可变参数模板,我的目标是接收所有类型、扩展它们并打印它们……我能够在一个函数中做到这一点(找到了一些例子)但是我无法在一个类中做到这一点在这里,我试图构建一个“Master”来容纳许多“Slaves”,每个 Slave 都应该从他那里继承一个 Slave_T,然后知道它的类型,并将其打印在 c'tor 上。

但出于某种原因,我无法修复模棱两可的编译错误。我试图避免将任何类型作为参数传递给函数。我尝试使用 enable_if 或 true/false_type 约定,但无法,任何人有什么想法吗?这是我的代码:(包括功能扩展)

有效的功能扩展:

template<typename T, typename... Targs>
void Print(T value, Targs... Fargs) // recursive variadic function
{
Print<T>();
Print(Fargs...); // recursive call
}

template<typename T>
void Print(T = NULL)
{
std::cout << typeid(T).name() << endl;
}

我需要帮助的类扩展:

#include <iostream>
#include <vector>
#include <type_traits>
#include <memory>
using namespace std;



struct Slave {
virtual char const* Type() = 0;
};

template<typename T>
struct Slave_T : public Slave{
virtual char const* Type() {
return typeid(T).name();
}
};

template <typename ...T>
struct Master {
Master()
{
MakeSlave<T...>();
cout << "All Slaves:" << endl;
for (auto const& slave : v){
cout << slave ->Type() << endl;
}
}
private:

template<typename T, typename ...Rest>
void MakeSlave()
{
MakeSlave<Rest...>(); MakeSlave<T>();
}

template<typename T>
void MakeSlave() {
v.push_back(new Slave_T<T>());
}

vector<shared_ptr<Slave>> v;
};

int main()
{
Master<int, double, char> m;
//Print("Hello", '!', 123, 123);
return 0;
}

谢谢!

阿隆

最佳答案

首先:为了允许多态模板,您已经定义了一个非模板化的纯虚拟基类Slave .你的模板类 Slave_T必须从它继承(你想要一个包含异构模板的 std::vector,对吧?)。并注意您正在使用由基类 Slave 定义的虚函数.我想你之前忘记写基类列表了 struct Slave_T :)

第二:在虚函数的重写中 Type() ,你写了Slave<T>::type而不是 Slave_T<T>::type .另外注意这句话需要typename它之前的关键字,因为is a reference to a dependent scope. .但是,另一方面,您可以访问 Slave_T模板参数 T ,所以,为什么你不简单地使用 T ? :)

第三:更喜欢使用 std::make_shared 而不是原始 new句子。

第四:喜欢 std::string 而不是 C 风格的原始字符串。

代码修复后编辑:

模板参数T私有(private)函数MakeSlave()隐藏类可变参数模板参数 T .您必须使用其他名称。

顺便说一下,错误是在 makeslave 的重载中是不明确的:你已经定义了一个带有模板参数的版本 T和可变参数 Params ,也就是说,典型的 HEAD TAIL 递归方法与可变参数包一起使用。但是,另一方面,您还定义了一个只有一个模板参数的版本。请注意,这会使第一个版本产生歧义,因为可变参数包可以为空,因此在您的基本情况下,编译器不知道使用哪个版本。

解决方案:

您可以使用哨兵类型来跟踪参数列表何时被完全处理。您使用此哨兵来启用/禁用基本情况以避免歧义:

template <typename ...T>
struct Master {
Master()
{
MakeSlave<T...,_my_centinel_type>();
cout << "All Slaves:" << endl;
for (auto const& slave : v){
cout << slave ->Type() << endl;
}
}
private:
struct _my_centinel_type {};

template<typename U, typename ...Rest>
typename std::enable_if<!std::is_same<U,_my_centinel_type>::value , void>::type MakeSlave()
{
v.push_back( std::make_shared<Slave_T<U>>());
MakeSlave<Rest...>();
}

template<typename U>
typename std::enable_if<std::is_same<U,_my_centinel_type>::value , void>::type MakeSlave(){
//The base case does anything
}

查看实际效果:http://ideone.com/FqMPXh#

关于c++ - 递归地扩展类和函数的可变参数模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18031139/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com