2015-06-30 2 views
-2

Моя проблема может быть мелочной, но, как новичок, я хочу узнать подробности и, следовательно, буду благодарен за каждого, кто указывает мои ошибки.Невозможно скомпилировать функцию C++

В моем файле заголовка, я определил функцию как этот

void GetFileNames(const fs::path&, const string&, vector<fs::path>&, const bool); 

Тогда определение функции выглядит следующим образом в GetFileNames.cpp:

void GetFileNames(const fs::path& root, const string& ext, vector<fs::path>& names, const bool recursiveflag) 
{ 
     if(!fs::exists(root) || !fs::is_directory(root)) 
     { 
       cout<<"The root path either does not exist, or is not a valid folder.\n"<<endl; 
       return; 
     } 

    if (recursiveflag) 
    { 
      fs::recursive_directory_iterator it(root); 
      fs::recursive_directory_iterator endit; 
    } 
    else 
    { 
      fs::directory_iterator it(root); 
      fs::directory_iterator endit; 
    } 

    while(it != endit) 
    { 
      if(fs::is_regular_file(*it) && it->path().extension() == ext) 
        names.push_back(it->path().filename()); 

      ++it; 
    } 
} 

Когда я затем попытаться скомпилировать тест программы .cpp, где функция была вызвана следующим образом:

int main(int argc, char** argv) 
{ 
     vector<fs::path> names; 
     fs::path root(argv[1]); 
     string ext(argv[2]); 
     GetFileNames(root,ext,names,true); 
     for(auto i = names.begin(); i!= names.end(); ++i) 
       cout<< (*i).string()<<endl; 
     return 0; 
} 

I recei произошла ошибка:

Scanning dependencies of target Test 
[ 33%] Building CXX object src/CMakeFiles/Test.dir/test.cpp.o 
[ 66%] Building CXX object src/CMakeFiles/Test.dir/GetFileNames.cpp.o 
/Users/ujjwalujjwal/prog/src/GetFileNames.cpp:22:8: error: use of undeclared identifier 'it' 
     while(it != endit) 
      ^
/Users/ujjwalujjwal/prog/src/GetFileNames.cpp:22:14: error: use of undeclared identifier 'endit' 
     while(it != endit) 
        ^
/Users/ujjwalujjwal/prog/src/GetFileNames.cpp:24:27: error: use of undeclared identifier 'it' 
       if(fs::is_regular_file(*it) && it->path().extension() == ext) 
             ^
/Users/ujjwalujjwal/prog/src/GetFileNames.cpp:24:34: error: use of undeclared identifier 'it' 
       if(fs::is_regular_file(*it) && it->path().extension() == ext) 
              ^
/Users/ujjwalujjwal/prog/src/GetFileNames.cpp:25:20: error: use of undeclared identifier 'it' 
         names.push_back(it->path().filename()); 
             ^
/Users/ujjwalujjwal/prog/src/GetFileNames.cpp:27:5: error: use of undeclared identifier 'it' 
       ++it; 
       ^
6 errors generated. 
make[2]: *** [src/CMakeFiles/Test.dir/GetFileNames.cpp.o] Error 1 
make[1]: *** [src/CMakeFiles/Test.dir/all] Error 2 
make: *** [all] Error 2 

Я, похоже, не понимаю, где именно я делаю концептуальную ошибку. Это кажется очень тривиальным, но я хотел бы понять, что происходит здесь.

+2

это не имеет никакого отношения к bool. ваши итераторы не входят в область 'while (it! = endit)', потому что вы объявляете их в if, если они меньше. – UmNyobe

+0

Вот идея.Если вы считаете, что ваша проблема вызвана X, проверьте эту гипотезу, удалив X из проблемы и увидев, если она исчезнет. – juanchopanza

ответ

3

Вы определяете Итераторов в предшествующее если-нибудь сферу:

fs::recursive_directory_iterator it(root); 
fs::recursive_directory_iterator endit; 

Поэтому, когда вы ссылаетесь их позже в цикле, пока они больше не существуют как переменные уничтожаются, как только ваш, если -else block закончен.

Как есть итераторы, которые имеют различные типы в зависимости от bool аргумента, возможно, придется фактически поместить время цикла внутри каждого из ваших if и else блоков, чтобы гарантировать, что итераторы все еще существуют, когда вы выполняете свой while цикл.

Однако вы решили продолжить, это не имеет никакого отношения к параметру boolean к вашей функции - обратите внимание на ошибки компилятора, поскольку они сообщают вам, что не так.

+0

Означает ли это, что мне пришлось бы писать одну и ту же копию в каждом блоке if-else? Это единственное решение? –

+0

Спасибо, я понял. Позаботимся об этих деталях с этого момента. –

1

it определен в другом блоке, вы не можете использовать его в вашем время цикла, если вы не определите его перед

0

Проблема заключается в бит кода ...

.... 
    while(it != endit) 
    { 
     if(fs::is_regular_file(*it) && it->path().extension() == ext) 
       names.push_back(it->path().filename()); 

     ++it; 
    } 
    .... 

.. . использует две переменные: «это» и «endit». Однако в обоих случаях, когда вы заявляете, что они находятся внутри {} блоков. Это делает объявление только локальным для этих блоков.

Ваша проблема несколько ухудшилась при каждом объявлении «it» и «endit» из разных типов.

Вы можете либо переместить декларацию за пределы локальных блоков и сделать их некоторого общего типа (в данном случае InputIterators), или вы можете переместить петлю, а в конце внутри обоих локальных блоков, как это ...

... 
    if (recursiveflag) 
    { 
     fs::recursive_directory_iterator it(root); 
     fs::recursive_directory_iterator endit; 

     while(it != endit) 
     { 
      if(fs::is_regular_file(*it) && it->path().extension() == ext) 
        names.push_back(it->path().filename()); 

      ++it; 
     } 
    } 
    else 
    { 
     fs::directory_iterator it(root); 
     fs::directory_iterator endit; 

     while(it != endit) 
     { 
      if(fs::is_regular_file(*it) && it->path().extension() == ext) 
        names.push_back(it->path().filename()); 

      ++it; 
     } 
    } 
... 

Хотя это приводит к ненужному дублированию кода и дополнительно способствует кошмарам для обслуживания.