C++模板中使用非实例化模板类型,会出现异常,例如模板示例代码:

//chain.h
#ifndef CHAIN_H
#define CHAIN_H

#include <iostream>
#include <list>


template<typename T>
class chain
{
    typedef std::list<T> LIST;

public:
    chain(){};
    void push(const T& x);
    void pop();

    void all();

private:
    LIST elems;
};

template<typename T>
void chain<T>::push(const T& x)
{
    //std::cout << x << std::endl;
    elems.push_back(x);
}

template<typename T>
void chain<T>::pop()
{
    elems.pop_back();
}

template<typename T>
void chain<T>::all()
{
    std::cout << "-------------------------------" << std::endl;
    std::cout << "list all elems: " << std::endl;

    LIST::iterator iter;
    for(iter=elems.begin(); iter!=elems.end(); ++iter )
    {
        std::cout << *iter << std::endl;
    }
    //std::cout << "-------------------------------" << std::endl;
}

#endif // CHAIN_H

调用模板的程序:

//main.cpp
#include <iostream>
#include "chain.h"

int main(int argc, char *argv[])
{
    std::cout << "start ..."  << std::endl;

    chain<char*> chain_string;
    chain_string.push("first");
    chain_string.push("second");
    chain_string.all();

    chain_string.pop();
    chain_string.pop();
    chain_string.all();

    std::cout << "end ..."  << std::endl;
    return 0;
}

Makefile内容如下:

OBJS = main.o
CC = g++
CFLAGS = -Wall -O -g

myprog : $(OBJS)
	$(CC) $^ -o $@

main.o : main.cpp chain.h
	$(CC) $(CFLAGS) -c $< -o $@

.PYONY: clean

clean:
	rm -rf $(OBJS)
	rm -rf myprog

命令行执行编译:

# make
g++ -Wall -O -g -c main.cpp -o main.o

In file included from main.cpp:2:0:
chain.h: In member function ‘void chain<T>::all()’:
chain.h:43:5: error: need ‘typename’ before ‘chain<T>::LIST:: iterator’ because ‘chain<T>::LIST’ is a dependent scope
    LIST::iterator iter;
    ^
chain.h:43:20: error: expected ‘;’ before ‘iter’
    LIST::iterator iter;
                   ^
chain.h:44:9: error: ‘iter’ was not declared in this scope
    for(iter=elems.begin(); iter!=elems.end(); ++iter )
        ^
main.cpp: In function ‘int main(int, char**)’:
main.cpp:9:30: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    chain_string.push("first");
                             ^
main.cpp:10:31: warning: deprecated conversion from string constant to ‘char*’ [-Wwrite-strings]
    chain_string.push("second");
                              ^
In file included from main.cpp:2:0:
chain.h: In instantiation of ‘void chain<T>::all() [with T = char*]’:
main.cpp:11:22:   required from here
chain.h:43:5: error: dependent-name ‘chain<T>::LIST:: iterator’ is parsed as a non-type, but instantiation yields a type
    LIST::iterator iter;
    ^
chain.h:43:5: note: say ‘typename chain<T>::LIST:: iterator’ if a type is meant
Makefile:9: recipe for target 'main.o' failed
make: *** [main.o] Error 1

主要是std::list还是一个模板类型, 如何实例化还需要取决于外部实际传进来的类型参数T,因此编译器为防止产生歧义,需要在前面添加一个typename关键字显式的声明这是一个模板类型,而非一个成员变量。

解决方法是在LIST前面添加一个typename关键字

typename LIST::iterator iter;

再次make编译不会产生错误。