다음과 같은 에러가 났다.
환경: GCC 4.1.2 20080704 (Red Hat 4.1.2-46) on CentOS 5.4
g++ -c classify_GSE_into_cluster_file_pathway.cpp
classify_GSE_into_cluster_file_pathway.cpp: In function ‘int main(int, const char**)’:
classify_GSE_into_cluster_file_pathway.cpp:152: error: invalid operands of types ‘std::ofstream*’ and ‘const char [20]’ to binary ‘operator<<’
에러의 의미를 그대로 해석해 보면, main 함수에서 에러가 났는데, 그 내용은 "
이다.
이렇게 연산자에 입력으로 들어 가는 값들을 operand라 한다. 예를 들어, 5 + 5.9 , 라는 연산을 본다면, 연산자 + 는 5 와 5.9 라는 두 개의 operand를 사용하고 있는 것이다.
위의 에러 메세지는 operand 2개를 필요로 하는 binary operator인 operator<< 에 std::ofstream* 과 const char[20] 이 operand로 들어 갔는데, 그럴 수 없다는 내용이다. 에러가 난 코드를 보자.
122 std::map<std::string,std::ofstream*> clusterpath2file;
123 std::map<std::string,std::ofstream*>::iterator find_pos;
124
125 // All pairs of cluster no. and pathways are to be stored in [all_cluster_pathway]
126 // but only for the pathways in [critical_pathways].
127 char temp[200] = "";
128 int file_count = 1;
129 std::string line;
130 for(pos = gse_file_name_list.begin(); pos != gse_file_name_list.end(); pos++){
131 //get_cluster_pathway_name(*pos, critical_pathways, &all_cluster_pathway, &content);
132 std::cout << *pos << std::endl;
133 std::ifstream ifile(pos->c_str());
134 if(ifile.is_open() == false) continue;
135 while(std::getline(ifile, line)){
136 if(line == "" || line[0] == '#') continue;
137 std::vector<std::string> v = split<std::string,string2string>(line, '\t');
138 if(v.size() != 10) continue;
139 if(critical_pathways.count(v[9]) == 0) continue;
140 std::string clusterpath = v[0] + ":" + v[1];
141 find_pos = clusterpath2file.find(clusterpath);
142 if(find_pos == clusterpath2file.end()){
143 sprintf(temp, (out_dir + "/path_cluster_corr_%d.txt").c_str(), file_count);
144 file_count++;
145 std::ofstream *out = new std::ofstream(temp);
146 *out << "INFO:SOURCE_CLUSTER_FILE_NAME:\t" << v[0] << std::endl;
147 *out << "INFO:PATHWAY_NAME:\t" << v[9] << std::endl;
148 *out << "!PATH_CLUSTER_CORR\t" << line << std::endl;
149 clusterpath2file.insert(std::make_pair<std::string,std::ofstream*>(clusterpath, out));
150 }
151 else{
152 find_pos->second << "!PATH_CLUSTER_CORR\t" << line << std::endl;
153 }
154 }
155 }
152 번째 줄을 보면 [find_pos->second] 이고, 123 번째 줄에 보면 [find_pos]는 다음과 같이 선언되어 있다.
ostream& operator<< (ostream& out, signed char c );
ostream& operator<< (ostream& out, unsigned char c );
ostream& operator<< (ostream& out, const char* s );
ostream& operator<< (ostream& out, const signed char* s );
ostream& operator<< (ostream& out, const unsigned char* s );
아마도 gcc는 위 나열된 전역 함수들 중 bold로 해 놓은 것을 호출하려 했을테지, 하지만 첫 번째 operand가 ostream& 이 아니라 ostream* 였기 때문에 작업을 할 수 없었을 것이다. 결국 operand type으로 ostream* 와 const char* 를 받는 operator<< 는 그 어디에도 없었기 때문에 위와 같은 에러 메세지가 나왔던 것이다.
해결은, 매우 간단히,
152 (*find_pos->second) << "!PATH_CLUSTER_CORR\t" << line << std::endl;
로 하면 되겠지.
여기서, 잠시 다른 얘기 하나. 위에서 operator<< 를 저렇게 연달아 쓸 수 있는 것은, 사실 C++에서 reference로 return 하는 것이 유용하게 사용된 좋은 예이다.
o << "a" << "\t" << 'b' << "\t" << 1 << std::endl;
은, 우선,
함수에 의해 호출되는데, 이 때 ostream& out 에는 o 가, const char* s 에는 "a" 가 들어가서 반환값으로 ostream&가 반환되는데, 물론 입력으로 들어 갔던 out이 반환되어야 하기 때문에, 위 경우 o 가 반환될 것이다. 따라서 3
의 반환값은 다시 o 이다! 여기서 다시 같은 방법으로 o와 "\t" 가 입력으로 들어가서 o 가 튀어 나온다. 그리고, 다시 'b'를 받기 위해 다음과 같은 전역함수가 실행될 것이다.
물론 동일하게 ostream& out에는 o 가, char c 에는 'b'가 들어간 후, 반환되는 것은 역시나 o 그 자신이 반환되겠지. 이런 식으로 계속 reference가 반환되기 때문에 operator<< 를 연달아서 계속 쓸 수 있는 것이다.
'컴퓨터 > 디버깅' 카테고리의 다른 글
segmentation fault의 원인 (1) | 2010.09.30 |
---|---|
cannot instantiate abstract class (0) | 2010.07.26 |
디버깅 공지사항 (0) | 2010.05.25 |
no matching function for call to (0) | 2010.05.24 |
for 문의 동작 순서 (1) | 2010.05.19 |