Er Kandarp Patel Er Kandarp Patel - 1 month ago 13
C++ Question

c++ extern string array not visible

I am new in C++ development , As I learn online about extern variable - I tried it to string variables and its working fine.But I have to work with string variable as its not working.Please look as follow.

globals.h

#include <iostream>

using namespace std;

#ifndef SIMULATIONFILEPARSER_GLOBALS_H
#define SIMULATIONFILEPARSER_GLOBALS_H
//sequence of files to be execute
extern string ipFiles[];
#endif //SIMULATIONFILEPARSER_GLOBALS_H


globals.cpp

#include "../headers/globals.h"
//sequence of files to be execute
string ipFiles[] = {"in.relaxSubstrate", "in.relaxFluid"};


main.cpp

#include <iostream>
#include "Source/headers/globals.h"

int main() {
for (string &ipFileName :ipFiles) {
std::cout << ipFileName << std::endl;
}
return 0;
}


When I try to run this project , It gives following error

C:\Users\king\ClionProjects\SimulationFileParser\main.cpp: In function 'int main()':
C:\Users\king\ClionProjects\SimulationFileParser\main.cpp:5:30: error: range-based 'for' expression of type 'std::__cxx11::basic_string<char> []' has incomplete type
for (string &ipFileName :ipFiles) {
^
CMakeFiles\SimulationFileParser.dir\build.make:61: recipe for target 'CMakeFiles/SimulationFileParser.dir/main.cpp.obj' failed
mingw32-make.exe[3]: *** [CMakeFiles/SimulationFileParser.dir/main.cpp.obj] Error 1
mingw32-make.exe[3]: *** Waiting for unfinished jobs....
mingw32-make.exe[2]: *** [CMakeFiles/SimulationFileParser.dir/all] Error 2
CMakeFiles\Makefile2:66: recipe for target 'CMakeFiles/SimulationFileParser.dir/all' failed
mingw32-make.exe[1]: *** [CMakeFiles/SimulationFileParser.dir/rule] Error 2
CMakeFiles\Makefile2:78: recipe for target 'CMakeFiles/SimulationFileParser.dir/rule' failed
mingw32-make.exe: *** [SimulationFileParser] Error 2
Makefile:117: recipe for target 'SimulationFileParser' failed

Answer

The compiler doesn't complain about a symbol, that's not visible. It's telling you, that the type is incomplete:

range-based 'for' expression of type 'std::__cxx11::basic_string []' has incomplete type

Until the compiler knows the size of the array, it cannot compile the range-based for loop. To change this, you need to declare a complete type. This could be an array with an explicit size, or - and that's the recommended solution - a standard container1:

globals.h

#pragma once

#include <string>
#include <vector>

extern std::vector<std::string> ipFiles;

globals.cpp

std::vector<std::string> ipFiles{"in.relaxSubstrate", "in.relaxFluid"};

You don't have to change main.cpp. But if you want to make it fancy, you could use auto as well as exercising const-correctness:

int main() {
    for (const auto& ipFileName : ipFiles) {
        std::cout << ipFileName << std::endl;
    }
    return 0;
}


1 The size of a standard container does not need to be known at compile time. All the compiler needs are the (forward) iterators to begin() and end() of the controlled sequence. An array, on the other hand, doesn't provide those as member functions, and the compiler needs to generate them. It needs to know the size to generate the equivalent of end().

Comments