如何使用模板模板参数实现该方法所需的通用接口的STL容器的通用方法 [英] How to implement generic method for STL containers that haven`t common interface needed for that method using template template parameter
问题描述
问题陈述(用于教育目的):
- 实施方法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屋!