Class 成员使用可变参数模板
Class with member that uses variadic template
我试图了解模板的工作原理,但我遇到了这个问题。现在,我完全知道它可以使用多态性来解决,但我很好奇是否可以仅使用模板来解决它。情况如下:
假设我有两种类型的队列,定义如下:
#include <queue>
template <typename GenType, typename Comparator>
class Priority
{
public:
Priority()
{ }
~Priority()
{ }
void insert(GenType const& t)
{ mQueue.push(t); }
private:
std::priority_queue<GenType, std::vector<GenType>, Comparator> mQueue;
};
template<typename GenType>
class FIFO
{
public:
FIFO()
{ }
~FIFO()
{ }
void insert(GenType const& t)
{ mList.push_front(t); }
private:
std::deque<GenType> mList;
};
现在,我有一个 class 可以使用 Queue
或 FIFO
(或任何其他类型的队列),如下所示:
// I'm not sure that this is how it should be declared...
template <typename GenType,
template<typename, typename...> class List>
class User
{
public:
User()
{ }
~User()
{ }
void add(GenType const& t)
{ mList.insert(t); }
private:
// This line gives an error.
List mList;
};
就目前而言,标记的行给出了一个错误,我理解这一点,因为我实际上没有将任何模板参数传递给 List
。问题是我不知道如何解决这个错误。
为了提供一些上下文,这个用例是能够让 User
class 采用任何类型的队列,并且可以像这样使用:
User<int, FIFO> u1;
// Not sure if it is this way:
User<int, Priority, std::less<int>> u2;
// Or this way:
User<int, Priority, std::less> u2;
关于如何解决这个问题有什么建议吗?
不要那样做。
相反,让您的 User
class 模板采用它将要使用的容器的 完整类型 ,并让容器指示容器的类型它需要的值:
template <typename Container>
class User
{
public:
using value_type = typename Container::value_type; // you'll have to add this
// typedef to your containers
User() = default;
~User() = default;
void add(value_type const& t)
{
mList.insert(t);
}
private:
Container mList;
};
这样,作为您 class 模板的用户,我可以提供正确的内容。如果我想使用你的优先级队列,我可以直接传入我想要的比较器:
User<Priority<int, std::less<>>> u;
否:
User<FIFO<int>> u2;
或者也许我写了自己的容器,它甚至不是 class 模板:
User<SpecialContainer> u3;
无论哪种方式,您的都可以。通用的就好。
已经有一个可接受的答案,但我想显示所需的语法。
private:
// This line doesn't give an error.
List<GenType> mList;
};
现在这一行也可以编译:
User<int, FIFO> u1;
最后两行无法编译,因为模板User
只接受两个参数。只需添加第三个参数。
我试图了解模板的工作原理,但我遇到了这个问题。现在,我完全知道它可以使用多态性来解决,但我很好奇是否可以仅使用模板来解决它。情况如下:
假设我有两种类型的队列,定义如下:
#include <queue>
template <typename GenType, typename Comparator>
class Priority
{
public:
Priority()
{ }
~Priority()
{ }
void insert(GenType const& t)
{ mQueue.push(t); }
private:
std::priority_queue<GenType, std::vector<GenType>, Comparator> mQueue;
};
template<typename GenType>
class FIFO
{
public:
FIFO()
{ }
~FIFO()
{ }
void insert(GenType const& t)
{ mList.push_front(t); }
private:
std::deque<GenType> mList;
};
现在,我有一个 class 可以使用 Queue
或 FIFO
(或任何其他类型的队列),如下所示:
// I'm not sure that this is how it should be declared...
template <typename GenType,
template<typename, typename...> class List>
class User
{
public:
User()
{ }
~User()
{ }
void add(GenType const& t)
{ mList.insert(t); }
private:
// This line gives an error.
List mList;
};
就目前而言,标记的行给出了一个错误,我理解这一点,因为我实际上没有将任何模板参数传递给 List
。问题是我不知道如何解决这个错误。
为了提供一些上下文,这个用例是能够让 User
class 采用任何类型的队列,并且可以像这样使用:
User<int, FIFO> u1;
// Not sure if it is this way:
User<int, Priority, std::less<int>> u2;
// Or this way:
User<int, Priority, std::less> u2;
关于如何解决这个问题有什么建议吗?
不要那样做。
相反,让您的 User
class 模板采用它将要使用的容器的 完整类型 ,并让容器指示容器的类型它需要的值:
template <typename Container>
class User
{
public:
using value_type = typename Container::value_type; // you'll have to add this
// typedef to your containers
User() = default;
~User() = default;
void add(value_type const& t)
{
mList.insert(t);
}
private:
Container mList;
};
这样,作为您 class 模板的用户,我可以提供正确的内容。如果我想使用你的优先级队列,我可以直接传入我想要的比较器:
User<Priority<int, std::less<>>> u;
否:
User<FIFO<int>> u2;
或者也许我写了自己的容器,它甚至不是 class 模板:
User<SpecialContainer> u3;
无论哪种方式,您的都可以。通用的就好。
已经有一个可接受的答案,但我想显示所需的语法。
private:
// This line doesn't give an error.
List<GenType> mList;
};
现在这一行也可以编译:
User<int, FIFO> u1;
最后两行无法编译,因为模板User
只接受两个参数。只需添加第三个参数。