c++ - 如何使用模板模板参数为该方法不需要通用接口(interface)的 STL 容器实现通用方法

标签 c++ templates stl c++11

问题陈述(用于教育目的):
- 实现适用于 STL 容器 vectorstackqueuedeque 的方法 printContainer。

我做了一个解决方案,但是我不喜欢它,因为代码太多。
我为解决问题所做的工作:
1。设计了通用函数,期望容器的统一接口(interface)用于操作:获取最后一个元素的值并从容器中删除该元素

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;
}

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

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>'

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

更新:

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

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() 实现了一个运行时选择,这意味着所有分支的代码都必须编译,即使恰好只有一个分支它们的计算结果为 true,并且并非所有容器(例如 vector)都提供函数 top()

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

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
}

在这里,我将编译时已知的 bool 模板参数传递给函数 f()。如果输入的类型为 X,我将传递 true,因此支持名为 foo() 的成员函数;如果输入的类型为 Y,我将传递 false,因此支持名为 bar() 的成员函数。

即使选择在编译时已知的 bool 值上工作,语句本身也会在运行时执行。编译器首先必须编译整个函数,包括 if 语句的 false 分支。

您正在寻找的是某种 static if construct ,不幸的是,它在 C++ 中不可用。

此处的传统解决方案基于重载,实际上看起来与您最初提供的解决方案类似。

关于c++ - 如何使用模板模板参数为该方法不需要通用接口(interface)的 STL 容器实现通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15600198/

相关文章:

c++ - 如何将 std::transform 与模板一起使用

c++ - push_back vs emplace_back

c++ - 延迟第三方库中静态变量的初始化

c++ - 模板化函数作为参数

c++ - 如何混淆本地变量?

c++ - 是否可以使用 C++ 中类似 mixin 的模式覆盖功能

c++ - 使用模板在编译时初始化数组指针的 const vector

c++ - std::list.sort(Predicate) 编译器错误

c++ - 如何在 QRC 文件中的另一个 qresource 下添加 qresource

c++ - 如何自动创建具有最新编译时间的文件并将其包含到库中?