如何使用模板模板参数实现该方法所需的通用接口的STL容器的通用方法 [英] How to implement generic method for STL containers that haven`t common interface needed for that method using template template parameter

查看:94
本文介绍了如何使用模板模板参数实现该方法所需的通用接口的STL容器的通用方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

问题陈述(用于教育目的):

- 实施方法printContainer,适用于STL容器 / code>, stack 队列 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<顶部(容器) ;
pop(container);
}
cout<< endl
cout<< * * * * * * * * * * *<< endl
}

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

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

我不会替换为这样: / strong>

  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 ,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 ,Base>))
c.pop_back();
else
return c.pop();
}

但它不工作,我得到错误:

 错误1错误C2784:'container< T,Base> :: value_type top(container< T,Base>&)':could not推导'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 ,Base>))
return c.back();
if(typeid(container).name == typeid(queue< T,Base>))
return c.front();
else
return c.top();
}

无法工作,因为 if / code>实现一个运行时选择,这意味着所有分支的代码必须编译,即使只有其中一个分支计算 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); //错误! bar()不是X

的成员函数y y;
f< false>(y); //错误! foo()不是Y的成员函数
}

布尔模板参数,在编译时已知,函数 f()。如果输入是 X ,则我传递 true ,因此支持一个成员函数 foo();如果输入类型为 Y ,则我传递 false ,因此支持一个成员函数 bar()



即使选择适用于编译时已知的布尔值,在运行时。编译器首先必须编译整个函数,包括 if 语句的 false

您正在寻找的是某种类型的 static if 构造,这在C ++中不可用。



这里的传统解决方案是基于重载的,其实就像你最初提供的一样。


Problem statement (for an educational purpose):
-Implement method printContainer which works for STL containers vector, stack, queue and deque.

I made a solution, but I don`t like it due to excessive amount of code.
What I did to solve the problem:
1. Designed generic function which expects uniform interface from containers for operations: get value of last element and erase that element from the container

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

For each container I implemented functions that allows to provide uniform interface (I want to refactor the following code snippet):

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

I wan`t to replace it with something like this:

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

but it doesn`t work, I get errors like :

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

Question:
that adjacements should I made in template template paramter to sort out errors, maybe there is something that I overlooked or exist logical errors.
Any way, any usefull information is welcomed.
Thanks in advance!

UPDATE:

// that is how I am trying to invoke the function

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

解决方案

This solution:

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

Won't work, because if() realizes a run-time selection, which means that the code of all branches must compile, even though exactly only one of them evaluates to true, and function top() is not provided by all containers (e.g. vector).

Consider this simpler example for an explanation:

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
}

Here, I am passing a boolean template argument, which is known at compile-time, to function f(). I am passing true if the input is of type X, and therefore supports a member function called foo(); and I am passing false if the input is of type Y, and therefore supports a member function called bar().

Even though the selection works on a boolean value which is known at compile-time, the statement itself is executed at run-time. The compiler will first have to compile the whole function, including the false branch of the if statement.

What you are looking for is some kind of static if construct, which is unfortunately not available in C++.

The traditional solution here is based on overloading, and looks in fact like the one you provided originally.

这篇关于如何使用模板模板参数实现该方法所需的通用接口的STL容器的通用方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆