从类模板中排除类型
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从类模板中排除类型相关的知识,希望对你有一定的参考价值。
我目前在使用stack
搞乱我的一个模板化课程时遇到了麻烦。
问题是像pusk_back
,begin
或end
这样的方法不能用于那种类型。
所以我的目标是防止包含stack<T>
实例化或添加一个条件阻止stack
实例到达代码的那些部分。
这是class
的样子:
template<typename T, template <typename...> typename U>
class contain {
public:
contain() : _container()
{
}
~contain()
{
}
void push(T const&data)
{
this->_container.push_back(data);
}
void aff()
{
std::for_each(_container.begin(), _container.end(),
[](T &var) {::aff(var);});
}
void add()
{
std::for_each(_container.begin(), _container.end(),
[](T &var) {::add(var);});
}
private:
U<T> _container;
};
我试图专门化模板,但无法找到语法,也无法在运行时检查变量的类型。
我必须承认,template
s对我来说仍然有点像黑魔法。我已成功地在各种情况下使用模板特化(如果我没有更好的想法)但从不使用模板参数。所以,我试过......
当我尝试使用coliru(编译器g++ (GCC) 8.1.0
)时,我开始使用-std=c++11
并很快出现了一些可怕的错误。为了我的运气,还有一个提示切换到-std=c++17
。我做了,事情变得更好了。我记得C ++ 11中没有很好地支持模板模板参数。对cppreference
的一瞥就证明我是对的:
template <parameter-list> typename(C ++ 17)|班级名称(可选)(1) template <parameter-list> typename(C ++ 17)|类名(可选)=默认(2) template <parameter-list> typename(C ++ 17)| class ... name(可选)(3)(自C ++ 11起)
1)具有可选名称的模板模板参数。 2)具有可选名称和默认值的模板模板参数。 3)具有可选名称的模板模板参数包。
有了这个澄清,我参加了OPs示例代码,并为template
添加了部分专业化
- 留下第一个参数
- 使用
std::stack
专门设置第二个参数。
实际上,这与具有类型或值参数的模板的专用方式没有太大区别。
cppreference
有一篇关于这个partial template specialization的文章,但是使用这个术语作为搜索关键词应该有很多书籍和教程的点击。 (我记得那本书我曾经学过的C ++模板也是如此 - 当然。)
所以,在这里我的小样本来证明这一点:
#include <iostream>
#include <stack>
#include <vector>
template<typename T, template <typename...> typename U>
class ContainerT {
private:
U<T> _container;
public:
ContainerT(): _container() { }
~ContainerT() = default;
ContainerT(const ContainerT&) = default;
ContainerT& operator=(const ContainerT&) = default;
bool empty() const { return _container.empty(); }
void push(const T &data) { _container.push_back(data); }
T pop()
{
const T data = _container.back();
_container.pop_back();
return data;
}
};
template<typename T>
class ContainerT<T, std::stack> {
private:
std::stack<T> _container;
public:
ContainerT(): _container() { }
~ContainerT() = default;
ContainerT(const ContainerT&) = default;
ContainerT& operator=(const ContainerT&) = default;
bool empty() const { return _container.empty(); }
void push(const T &data) { _container.push(data); }
T pop()
{
const T data = _container.top();
_container.pop();
return data;
}
};
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";
"; __VA_ARGS__
int main()
{
// for std::vector
DEBUG(ContainerT<int, std::vector> vec);
DEBUG(vec.push(1); vec.push(2); vec.push(3));
DEBUG(while (!vec.empty()) std::cout << vec.pop() << '
');
// for std::stack
DEBUG(ContainerT<int, std::stack> stk);
DEBUG(stk.push(1); stk.push(2); stk.push(3));
DEBUG(while (!stk.empty()) std::cout << stk.pop() << '
');
// done
return 0;
}
很明显,ContainerT
是ContainerT<int, std::vector>
的例子。否则,push()
方法无法编译。
对于ContainerT<int, std::stack>
,使用专业化。 (再次,否则,push()
方法无法编译。)
输出:
ContainerT<int, std::vector> vec;
vec.push(1); vec.push(2); vec.push(3);
while (!vec.empty()) std::cout << vec.pop() << '
';
3
2
1
ContainerT<int, std::stack> stk;
stk.push(1); stk.push(2); stk.push(3);
while (!stk.empty()) std::cout << stk.pop() << '
';
3
2
1
以上是关于从类模板中排除类型的主要内容,如果未能解决你的问题,请参考以下文章