为什么这个取模板参数的函数没有编译
Why does this function that takes template template parameter not compile?
我试图用我在上一个问题中得到的优秀答案来理解这个问题,但我不明白为什么这个代码不能编译。
#include <iostream>
#include <ostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <memory>
template <typename T,
template <typename ELEM,
typename = std::allocator<ELEM> >
class CONT = std::deque>
class Stack {
public:
typedef typename CONT<T>::size_type size_type;
private:
CONT<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
T top() const; // return top element
bool empty() const { // return whether the stack is empty
return elems.empty();
}
size_type size();
};
template <typename T, template <typename,typename> class CONT>
void Stack<T,CONT>::push (T const& elem)
{
elems.push_back(elem); // append copy of passed elem
}
template<typename T, template <typename,typename> class CONT>
void Stack<T,CONT>::pop ()
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
elems.pop_back(); // remove last element
}
template <typename T, template <typename,typename> class CONT>
T Stack<T,CONT>::top () const
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::top(): empty stack");
}
return elems.back(); // return copy of last element
}
template<typename T,
template<typename, typename= std::allocator<T> > class CONT>
typename Stack<T, CONT>::size_type Stack<T, CONT>::size()
{
return elems.size();
}
template <typename T,
template <typename ELEM, typename = std::allocator<ELEM> > class CONT>
static inline void Pout(const CONT<T>& container)
{
typedef typename CONT<T >::size_type size_type;
size_type idx = 0;
size_type sz = CONT<T>::size();
CONT<T> temp = container;
std::cout << '[';
while (idx < sz)
{
std::cout << temp.top();
temp.pop();
idx++;
if (idx == sz) break;
std::cout << ", ";
}
std::cout << "]";
}
int main()
{
try {
Stack<int, std::vector > vStack;
//...
vStack.push(42);
vStack.push(7);
Pout<Stack<int, std::vector > >(vStack);
}
catch (std::exception const& ex) {
std::cerr << "Exception: " << ex.what() << std::endl;
}
}
我使用g++4.3.4:得到编译器错误
stack8test.cpp: In function int main():
stack8test.cpp:28: error: no matching function for call to Pout(Stack<int, std::vector>&)
make: *** [stack8test.o] Error 1
我会感谢你的帮助。
我做了一些更改,注释掉了函数调用Pout>(vStack),并将vStack的内容打印到std::cout。这是新代码。它按预期编译和工作:
#include <iostream>
#include <ostream>
#include <string>
#include <cstdlib>
#include <vector>
#include <memory>
#include <deque>
#include <stdexcept>
template <typename T,
template <typename ELEM,
typename = std::allocator<ELEM> >
class CONT = std::deque>
class Stack {
public:
typedef typename CONT<T>::size_type size_type;
typedef typename CONT<T>::value_type value_type;
private:
CONT<T> elems; // elements
public:
void push(T const&); // push element
void pop(); // pop element
T top() const; // return top element
bool empty() const { // return whether the stack is empty
return elems.empty();
}
size_type size();
void Pout();
};
template <typename T, template <typename,typename> class CONT>
void Stack<T,CONT>::push (T const& elem)
{
elems.push_back(elem); // append copy of passed elem
}
template<typename T, template <typename,typename> class CONT>
void Stack<T,CONT>::pop ()
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::pop(): empty stack");
}
elems.pop_back(); // remove last element
}
template <typename T, template <typename,typename> class CONT>
T Stack<T,CONT>::top () const
{
if (elems.empty()) {
throw std::out_of_range("Stack<>::top(): empty stack");
}
return elems.back(); // return copy of last element
}
template<typename T,
template<typename, typename= std::allocator<T> > class CONT>
typename Stack<T, CONT>::size_type Stack<T, CONT>::size()
{
return elems.size();
}
template <typename T,
template<typename, typename = std::allocator<T> > class CONT>
void Stack<T, CONT>::Pout()
{
size_type idx = 0;
size_type sz = size();
CONT<T> temp(elems); // make a temp copy of the underlying container and print the temp, since printing is destructive. Note that the underlying CONT must already support copy constructor.
std::cout << std::endl << '[';
while (idx < sz)
{
std::cout << temp.back();
temp.pop_back();
idx++;
if (idx == sz) break;
std::cout << ", ";
}
std::cout << "]" << std::endl;;
}
template <typename T,
template <typename ELEM, typename = std::allocator<ELEM> > class CONT>
void Pout(const CONT<T>& container)
{
typedef typename CONT<T >::size_type size_type;
size_type idx = 0;
size_type sz = CONT<T>::size();
CONT<T> temp = container;
std::cout << '[';
while (idx < sz)
{
std::cout << temp.top();
temp.pop();
idx++;
if (idx == sz) break;
std::cout << ", ";
}
std::cout << "]";
}
int main()
{
try {
Stack<int, std::vector > vStack;
//...
vStack.push(42);
vStack.push(7);
// Pout<Stack<int, std::vector > >(vStack);
vStack.Pout();
std::cout << "vStack = [" << vStack.top(); vStack.pop();
std::cout << ", " << vStack.top() << "]" << std::endl; vStack.pop();
}
catch (std::exception const& ex) {
std::cerr << "Exception: " << ex.what() << std::endl;
}
}
编译器输出为:
g++ -O2 -g -Wall -c -o stack8test stack8test.cpp
运行程序,我得到:
./stack8test
vStack = [7, 42]
我真正的问题是为函数模板Pout找到正确的语法来打印类模板Stack的内容。为了澄清,我的意图是将类模板Stack实现为T类型元素的容器。我想根据std::vector或std::deque,甚至std::list类型的std容器来实现Stack。
我称Pout为:
Pout<int, Stack<int, std::vector>>(vStack);
但编译器仍然说:
stack8test.cpp: In function int main():
stack8test.cpp:137: error: no matching function for call to Pout(Stack<int, std::vector>&)
make: *** [stack8test.o] Error 1
更新:为了解决我最初的全局(即非成员)函数问题,将Stack的内容打印到std::cout,我将Pout()定义为成员函数。它按预期编译和工作。为全局函数找到正确的语法仍然是一个挑战。
事情太复杂了。您应该让编译器为您推断出尽可能多的信息,而不是编写
template <typename T,
template <typename ELEM, typename = std::allocator<ELEM> > class CONT>
static inline void Pout(const CONT<T>& container)
只需写入
template <class CONT>
static inline void Pout(const CONT& container)
STL就是这样做的。如果您需要访问容器的底层类型,再次使用STL方法,并将value_type
typedef添加到类中:
class Stack {
public:
...
typedef T value_type;
...
}
然后,您可以在函数中以CONT::value_type
的形式访问它。但是,您甚至没有在Pout
函数中使用这些信息。
其他一些错误:
- 将
size
函数标记为const
- 不要使用
static inline
指定你的函数,除非你100%确定你知道你在做什么。也许,你不是
代码在修复这些错误后进行编译,但总体设计相当糟糕。
相关文章:
- 跨模板化函数编译的静态变量
- 无法使用 LoadObject() 函数编译 UE4 Actor。
- 为什么在使用转换构造函数编译代码时需要 const 复制构造函数?
- 函数编译,即使它不接受整数
- 使用C 模板函数编译时间递归
- 安卓 JNI - 'raw'函数编译失败
- C++就地析构函数编译警告
- 对 TR1 使用 boost 时提升数学特殊函数编译错误
- 显式复制构造函数编译错误
- 使用SSE内部函数编译一个简单的c++程序
- 函数编译时错误
- 模板函数编译错误
- C++:使用类型名作为基的模板类调用函数编译时错误
- 将 MATLAB 函数编译成可以在 linux 终端上运行的东西,w.out MATLAB
- boost::绑定不要使用成员模板函数编译
- C++函数编译错误
- 加速模板函数编译
- 如何在C++中使用辅助函数编译以下flex文件
- 如何让g++使用move构造函数编译c++11代码
- 同时将一组函数编译为.LIB和.DLL