如何使用模板模板参数为没有该方法所需的公共接口的 STL 容器实现通用方法

2024-04-23

问题陈述(为教育性的目的):
-实现适用于STL容器的方法printContainervector, stack, queue and deque.

我提出了一个解决方案,但由于代码量过多,我不喜欢它。
我为解决问题所做的事情:
1.设计通用函数,期望容器提供统一的操作接口:获取最后一个元素的值并从容器中删除该元素

template <typename T>
void printContainer(T container)
{
    cout << " * * * * * * * * * * " << endl;
    cout << " operator printContainer(T container). Stack, queue, priority queue" 
         << endl;
    cout << typeid(container).name() << endl;

    while (!container.empty())
    {
            cout << top(container) << "    ";
            pop(container);
    }
    cout << endl;
    cout << " * * * * * * * * * * * " << endl;
}

对于每个容器,我实现了允许提供统一接口的功能 (我想重构以下代码片段):

template <typename T>
typename vector<T>::value_type top(const vector<T>& v)
{
    return v.back();
}
template <typename T, typename Base>
typename stack<T, Base>::value_type top(const stack<T, Base>& s)
{
    return s.top();
}

template <typename T, typename Base>
typename queue<T, Base>::value_type top(const queue<T, Base>& q)
{
    return q.front();
}

template <typename T, typename Base>
typename priority_queue<T, Base>::value_type top(const priority_queue<T, 
                                                              Base>& pq)
{
    return pq.top();
}

template <typename T>
void pop(vector<T>& v)
{
    return v.pop_back();
}

template <typename T, typename Base>
void pop(stack<T, Base>& s)
{
    return s.pop();
}

template <typename T, typename Base>
void pop(queue<T, Base>& q)
{
    return q.pop();
}

template <typename T, typename Base>
void pop(priority_queue<T,Base>& pq)
{
    return pq.pop();
}

我想用这样的东西替换它:

template <typename T, typename Base, template<typename T, class Base, 
class ALL = std::allocator<T>> class container>
typename container<T,Base>::value_type top(container<T,Base>& c)
{
    if (typeid(container).name == typeid(vector<T,Base>))
        return c.back();
    if (typeid(container).name == typeid(queue<T,Base>))
        return c.front();
    else
        return c.top();
}

template <typename T, typename Base, template<typename T, class Base, 
class ALL = std::allocator<T>> class container>
typename container<T,Base>::value_type pop(container<T,Base>& c)
{
    if (typeid(container).name == typeid(vector<T,Base>))
        c.pop_back();
    else
        return c.pop();
}

但它不起作用,我收到如下错误:

Error   1   error C2784: 'container<T,Base>::value_type top(container<T,Base> &)' : could not deduce template argument for 'container<T,Base> &' from 'std::stack<_Ty>'

问题:
我应该在模板模板参数中进行邻接来解决错误,也许有一些我忽略的东西或存在逻辑错误。
无论如何,欢迎任何有用的信息。
提前致谢!

UPDATE:

// 这就是我尝试调用该函数的方式

int arr[] = {1,2,3,4,5,6,7,8,9,0};
    stack<int> s(deque<int>(arr, arr + sizeof(arr) / sizeof(arr[0])));;
    queue<int> q(deque<int>(arr, arr + sizeof(arr) / sizeof(arr[0])));
    priority_queue<int> pq(arr, arr + sizeof(arr) / sizeof(arr[0]));
    printContainer(s);
    printContainer(q);
    printContainer(pq);

这个解决方案:

template <typename T, typename Base, template<typename T, class Base, 
class ALL = std::allocator<T>> class container>
typename container<T,Base>::value_type top(container<T,Base>& c)
{
    if (typeid(container).name == typeid(vector<T,Base>))
        return c.back();
    if (typeid(container).name == typeid(queue<T,Base>))
        return c.front();
    else
        return c.top();
}

行不通,因为if()实现了一个run-time选择,这意味着所有分支的代码都必须编译,即使只有其中一个分支的计算结果为true,和函数top()并非所有容器都提供(例如vector).

考虑这个更简单的例子来进行解释:

struct X { void foo() { } };
struct Y { void bar() { } };

template<bool b, typename T>
void f(T t)
{
    if (b)
    {
        t.foo();
    }
    else
    {
        t.bar();
    }
}

int main()
{
    X x;
    f<true>(x); // ERROR! bar() is not a member function of X 

    Y y;
    f<false>(y); // ERROR! foo() is not a member function of Y
}

在这里,我传递一个布尔模板参数(在编译时已知)来运行f()。我正在路过true如果输入是类型X,因此支持一个名为的成员函数foo();我正在路过false如果输入是类型Y,因此支持一个名为的成员函数bar().

尽管选择适用于编译时已知的布尔值,但语句本身是在运行时执行的。编译器首先必须编译整个函数,包括false的分支if陈述。

你正在寻找的是某种static if构造 http://channel9.msdn.com/Events/GoingNative/GoingNative-2012/Static-If-I-Had-a-Hammer,不幸的是,这在 C++ 中不可用。

这里的传统解决方案基于重载,实际上看起来就像您最初提供的那样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用模板模板参数为没有该方法所需的公共接口的 STL 容器实现通用方法 的相关文章

  • 知识树中的段错误

    我正在用 c 实现一个可以从文件中读取的知识树 我的 newStr 函数出现段错误 我无法用这个问题测试我的其余代码 我对 c 没有太多经验 任何帮助将不胜感激 我的 c 文件 包括 包括 include 动物 h 包括 包括 return
  • 这些比较应该返回什么?

    我有一个使用 string compare string string 对某些值进行排序的应用程序 我不明白的是为什么 1022 比较小于 10 23 而 10 23 比较小于 1024 是否有特定于 值的东西导致了这个结果 string
  • 未初始化成员的警告在 C++11 上消失

    我编译这个简单的程序 include
  • 使用回溯(而不是 DFS)背后的直觉

    我正在解决单词搜索 https leetcode com problems word search description LeetCode com 上的问题 给定一个 2D 板和一个单词 查找该单词是否存在于网格中 该单词可以由顺序相邻单
  • 使用 SFML 绘制文本时出现段错误

    我做了一个Button应该绘制一些顶点和字符串的类RenderWindow 这是删除了不相关部分的代码 here http pastebin com 4a5RuS2y是完整的代码 namespace game class Button pu
  • 如何吞咽……有具体原因的异常

    在这个方法中 public static void Detach try using var master new DataContext Data Source LocalDB MSSQLLocalDB Initial Catalog m
  • C# - 当站点上没有活动时,Quartz 调度程序停止运行

    我用quartz调度器创建了asp net站点 该作业正在后台运行 站点上没有其他活动 Quartz 调度程序每 30 分钟调度一次 IIS启动后 Scheduler运行正常 但一段时间后 Scheduler 停止运行 大约 1 小时 如果
  • 再次对存储库和持久性一无所知

    这就是我要做的 我有一个通用的存储库类Repository
  • 将supportedRuntime嵌入到exe文件中

    我需要将仅包含supportedRuntime 设置的app config 文件嵌入到我的exe 文件中 我尝试执行构建操作嵌入资源 但它现在没有从配置文件中读取值 并且它不起作用 这是我的配置文件
  • 创建新视图时如何初始化视图模型中的属性?

    我有一个应用程序 可以打开一个视图 允许您搜索数据 然而 为了进行搜索 用户必须选择他想要在什么类别下进行搜索 目前 我正在尝试弄清楚如何将所选类别从主视图模型 作为 int 传递到新搜索视图的视图模型 目前我正在尝试在主视图中使用类似的东
  • 使用箭头键滚动可滚动控件

    我正在使用一个ScrollableControl在我的 C 项目中 我想知道如何将箭头键映射到垂直 水平滚动 编辑 我的图片框获得焦点 并且我设法映射滚动键 这里的问题是 当我按下箭头键时 它会滚动一次 然后失去焦点 将其交给滚动查看器旁边
  • 消息在事务处理时未到达 MSMQ

    我在本地计算机中创建了一个私有 MSMQ 我使用以下 C 代码将消息发送到队列 当我将队列更改为事务性队列时 消息未到达 MSMQ 但是 Send 方法中没有抛出异常 我需要做出什么改变才能使其发挥作用 using System using
  • 使用 boost 几何检查两条线是否有交点

    是否可以使用 boost geometry 检查两条线段 每条线段由二维中的两个点给出 是否彼此相交 如果可能的话 boost geometry 是否还允许检查特殊情况 例如另一条线上只有一个点 数字上 或者两条线相等 如果你具体谈论Boo
  • BackgroundWorker 如何决定在哪个线程上运行 RunWorkerCompleted 处理程序?

    我试图弄清楚 BGW 在工作完成后如何决定运行 RunWorkerCompleted 处理程序的线程 我的初始测试使用 WinForm 应用程序 在 UI 线程上 我开始bgw1 RunWorkerAsync 然后我尝试开始bgw2 Run
  • 制作 C# 项目 DLL 和 EXE

    我正在开发一个项目 需要有一个可执行文件以便用户可以运行配置界面和一个可以嵌入其他项目以使用其他一些功能的 DLL 有没有办法让 Visual Studio 同时生成可执行文件和 DLL 而不是每次都手动切换 我同意 TJMonk15 的观
  • 显示具有相同节点值的多个 XML 数据条目

    我有一个 XML 文档 其中包含课程信息 如下所示
  • 使用 MVVM 绑定 Xamarin.Forms 中的属性

    我在使用 Xamarin Forms 和 MVVM 制作游戏时遇到问题 游戏中有一艘由用户控制的潜艇 并且有水雷掉落 因此用户必须避开这些水雷 这些地雷是在运行时使用 2 个计时器生成的 因此我用 XAML 中的 CollectionVie
  • 多线程文件写入

    我正在尝试使用多个线程写入大文件的不同部分 就像分段文件下载器所做的那样 我的问题是 执行此操作的安全方法是什么 我是否打开文件进行写入 创建线程 将 Stream 对象传递给每个线程 我不希望发生错误 因为多个线程可能同时访问同一个对象
  • 索引 getter 中的 IndexOutOfRangeException

    在我的索引属性中 我检查索引是否超出范围 如果是的话 我抛出一个IndexOutOfBoundsException 当我运行代码分析器 在 VS12 中 时 它抱怨 CA1065 意外位置出现意外异常 参考CA1065的描述 仅 Syste
  • C# StreamReader 使用分隔符保存到数组

    我有一个文本文件 其中包含制表符分隔的数据 我在 C 应用程序中需要的是从文本文件中读取一行并将它们保存到一个数组中 在每个位置将它们分开 t 然后我对下一行做同样的事情 My code StreamReader sr new Stream

随机推荐