gpt4 book ai didi

c++ - 从类模板中排除类型

转载 作者:行者123 更新时间:2023-11-30 04:52:39 25 4
gpt4 key购买 nike

我目前遇到了 stack 的问题弄乱了我的一个模板类。
问题是像 pusk_back 这样的方法, beginend不适用于该类型。
所以我的目标是防止 contain 被实例化为 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对我来说,这仍然有点像黑魔法。我已经在各种情况下成功地使用了模板特化(如果我没有更好的主意的话),但从未使用过模板参数。所以,我尝试...

当我尝试使用 coliru(编译器 g++ (GCC) 8.1.0)时,我从 -std=c++11 开始很快就出现了一些可怕的错误。幸运的是,还有切换到 -std=c++17 的提示。 .我做到了,事情立刻变得好多了。我大致记得模板模板参数在 C++11 中没有得到很好的支持。快速浏览 cppreference证明我是对的:

Template template parameter

template < parameter-list > typename (C++17) | class name(optional) (1)
template < parameter-list > typename (C++17) | class name(optional) = default (2)
template < parameter-list > typename (C++17) | class ... name(optional) (3) (since C++11)

1) A template template parameter with an optional name.
2) A template template parameter with an optional name and a default.
3) A template template parameter pack with an optional name.

澄清了这一点后,我使用了部分 OP 示例代码并为 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__ << ";\n"; __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() << '\n');
// 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() << '\n');
// done
return 0;
}

很明显ContainerTContainerT<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() << '\n';
3
2
1
ContainerT<int, std::stack> stk;
stk.push(1); stk.push(2); stk.push(3);
while (!stk.empty()) std::cout << stk.pop() << '\n';
3
2
1

Live Demo on coliru

关于c++ - 从类模板中排除类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54262164/

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