Thread: Some function declarations in the .h file are ignored by the C++ compiler

  1. #1
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81

    Some function declarations in the .h file are ignored by the C++ compiler

    I am probably making a trivial mistake that I cannot see, but the g++ compiler is ignoring some function declarations in the .h file, and whether these function declarations are present or not, the executable program is created without any reported errors, and its output seems to be correct. But if I remove some other functions from the .h file, then there is an error reported by the g++ compiler.

    I can imagine two possible reasons for this situation: One possibility is that perhaps the fact the std::map that I am using to create a map whose elements are in fact functions, is causing some hidden problems. Or is it possible that I have altered the settings of my GVIM editor (Ubuntu Linux) in such a way that some invisible characters were introduced?

    Anyway, here is the entire code that is working.

    1) First of all, here is the text file "FileForNamesOfFunctions.TXT" that the main program reads the names of the functions that will be executed:

    function2
    function3
    function5
    function6


    2) Here is the .h file "h_file.h "of the main program:

    Code:
    
    // If I remove any of the following three function declarations
    // below, the g++ compiler reports an error:
    void TestChosenFunctions(); 
    void SetUpMapOfFunctionsToActualFunctions();
    void GetControlFunctionNamesFromDiskFile();
    
    
    // But it's OK to remove the following function declarations below
    //void function0(double); 
    //void function1(double);
    //void function2(double);
    //void function3(double);
    //void function4(double);
    //void function5(double);
    //void function6(double);
    3) Here is the main program file "MapsAndFunctions.cpp" that contains everything except the function declarations:

    Code:
    
    #include <fstream>
    #include <iostream>
    #include <sstream>
    #include <string>
    
    
    #include <vector>
    #include <map>
    
    #include "h_file.h"
    
    using namespace std;
    
    vector<string> vec_NamesOfFunctions;
    map<string, void (*)(double) > Map_NamesOfFunctionsToActualFunctions;
    
    
    
    
    int main()
    {
         TestChosenFunctions( ); 
    }
    
    
    void TestChosenFunctions( )  { 
                        
        int  junk;
    
    
        SetUpMapOfFunctionsToActualFunctions();
    
    
        GetControlFunctionNamesFromDiskFile();
    
    
        double x=1.0;
        cout << "Here x = 1.0" << endl;
        cout << "We selectively call only those functions whose names were written in the text file:" << endl;
        for( auto itr=vec_NamesOfFunctions.begin(), end=vec_NamesOfFunctions.end() ; itr != end; ++itr)
        { 
        if( Map_NamesOfFunctionsToActualFunctions.count(*itr) != 0 )
        {
                  Map_NamesOfFunctionsToActualFunctions[ *itr ]( x )  ;
        }
        else
        {
           cout << "Error: Function name missing from the map!" << endl;
        }
        }
        cout << "------------------------------------" << endl;
    
    
     }
    
    
     void GetControlFunctionNamesFromDiskFile(   )
    {
          string ControlParamFileFunctionsForFunctions = "FileForNamesOfFunctions.TXT";
          istringstream instream;   // Declare an input string stream
          ifstream inFile;
          string  firstStringOfLine;
          string s;
    
    
          inFile.open( ControlParamFileFunctionsForFunctions.c_str(), ios::in);
          if ( ! inFile.is_open() )
          {
                cout << "Could not open Key Text Input file!" << endl;
               exit(1);
          }
          while(  getline(inFile, s)  )
          {  
               instream.clear();
           instream.str(s);        
           instream >> firstStringOfLine;
               vec_NamesOfFunctions.push_back(firstStringOfLine);
          }
        
         inFile.close(); 
         cout << "The function names written in the disk file are: " << endl; 
         for( auto itr=vec_NamesOfFunctions.begin(), end =vec_NamesOfFunctions.end(); itr != end;  ++itr)
         {
        cout<<  *itr << endl; ;
         }
         cout << "---------------------------------------------" << endl; 
    
    
    }
    
    
    void function0(double x) {cout<<"function0 prints 0*x = " << 0*x << endl; }
    void function1(double x) {cout<<"function1 prints 1*x = " << 1*x << endl; }
    void function2(double x) {cout<<"function2 prints 2*x = " << 2*x << endl; }
    void function3(double x) {cout<<"function3 prints 3*x = " << 3*x << endl; }
    void function4(double x) {cout<<"function4 prints 4*x = " << 4*x << endl; }
    void function5(double x) {cout<<"function5 prints 5*x = " << 5*x << endl; }
    void function6(double x) {cout<<"function6 prints 6*x = " << 6*x << endl; }
    
    
    
    
    void SetUpMapOfFunctionsToActualFunctions()
    {
        Map_NamesOfFunctionsToActualFunctions["function0"]=function0;
        Map_NamesOfFunctionsToActualFunctions["function1"]=function1;
        Map_NamesOfFunctionsToActualFunctions["function2"]=function2;
        Map_NamesOfFunctionsToActualFunctions["function3"]=function3;
        Map_NamesOfFunctionsToActualFunctions["function4"]=function4;
        Map_NamesOfFunctionsToActualFunctions["function5"]=function5;
        Map_NamesOfFunctionsToActualFunctions["function6"]=function6;
    
    
        
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    4) Here is the output of the program which seems to be correct:

    The function names written in the disk file are:
    function2
    function3
    function5
    function6
    ---------------------------------------------
    Here x = 1.0
    We selectively call only those functions whose names were written in the text file:
    function2 prints 2*x = 2
    function3 prints 3*x = 3
    function5 prints 5*x = 5
    function6 prints 6*x = 6
    ------------------------------------
    administrator@ubuntu:~/2013-CPPworks/Junk1$ ./a.out
    The function names written in the disk file are:
    function2
    function3
    function5
    function6
    ---------------------------------------------
    Here x = 1.0
    We selectively call only those functions whose names were written in the text file:
    function2 prints 2*x = 2
    function3 prints 3*x = 3
    function5 prints 5*x = 5
    function6 prints 6*x = 6
    ------------------------------------

    I have used the std=c++0x option of g++ for this program, by typing exactly this line:

    g++ -std=c++0x MapsAndFunctions.cpp

    But in a bigger program that does not use C++0x, I have similar problems. In the other program (which I am not revealing here), if I add more functions to the std::map (similar to the situation above), this time I do get a compiler error which disappears only if I add the function declarations to the actual program that uses these functions, adding the function declarations to the .h file did not prevent the compiler error at that time. (And in the latter case, the compiler error was exactly in the lines such as "MyMap["functionName"] = myFunction; ", and this error disappeared only when I added the function declaration to the .cpp file, it was not enough to put the function declaration in the .h file. But this happened only for some of the new functions used by the std::map (not all of them in the map), which makes me worry that the GVIM editor is introducing invisible characters after I made a mistake in the settings. Is this possible?)
    Last edited by FortranLevelC++; 06-19-2013 at 07:22 PM.

  2. #2
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    I am probably making a trivial mistake that I cannot see, but the g++ compiler is ignoring some function declarations in the .h file, and whether these function declarations are present or not, the executable function is created without any reported errors, and its output seems to be correct.
    O_o

    The only place you have used the relevant functions directly comes after the definitions of those functions which also serves as declarations.

    which I am not revealing here
    Well, you probably will not get help related to errors in that code.

    Soma

  3. #3
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    I don't know if this is a habit for you or not, but names such as these:

    Map_NamesOfFunctionsToActualFunctions
    ControlParamFileFunctionsForFunctions
    GetControlFunctionNamesFromDiskFile

    ..are way, way too long and overly descriptive, it's bordeline comical in this case.

    Map_NamesOfFunctionsToActualFunctions could easily just be "functions", "function_names", "fmap", "function_map" or so on, it adds nothing to the code, in fact it decreases readability and i imagine it is a pain to type out, or even remember.
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  4. #4
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81
    Quote Originally Posted by phantomotap View Post
    O_o

    The only place you have used the relevant functions directly comes after the definitions of those functions which also serves as declarations.



    Well, you probably will not get help related to errors in that code.

    Soma
    My sincere apologies!

    You were correct, because if I directly set up the map of functions inside the program (without using the function that sets up the map), then I do have to declare the mentioned functions in the .h file.

    But on this occasion, it seems that I have found the source of the problem. It does seem to be invisible characters I have been introducing when I hit the return key after I add the names of the functions in the text file that the program reads in order to decide which functions to execute from the map.

    Here is the new version of the program that has a faulty output.

    1) First of all, here is the new text file "FileForNamesOfFunctions.TXT" that has 3 blank lines after the names of the functions (which I caused by hitting the return key):
    function2
    function3
    function5
    function6


    Here is the code again (modified by setting up the map directly at the beginning, which makes it necessary to put the function declarations inside the header file.) But the relevant change is the new functions I have created in the program:

    Code:
    
    #include <fstream>
    #include <iostream>
    #include <sstream>
    #include <string>
    
    
    #include <vector>
    #include <map>
    
    
    #include "h_file.h"
    
    
    using namespace std;
    
    
    
    
    vector<string> vec_NamesOfFunctions;
    map<string, void (*)(double) > Map_NamesOfFunctionsToActualFunctions;
    
    
    
    
    int main()
    {
         TestChosenFunctions( ); 
    }
    
    
    void TestChosenFunctions( )  {                     
        int  junk;
    
    
        
        Map_NamesOfFunctionsToActualFunctions["function0"]=function0;
        Map_NamesOfFunctionsToActualFunctions["function1"]=function1;
        Map_NamesOfFunctionsToActualFunctions["function2"]=function2;
        Map_NamesOfFunctionsToActualFunctions["function3"]=function3;
        Map_NamesOfFunctionsToActualFunctions["function4"]=function4;
        Map_NamesOfFunctionsToActualFunctions["function5"]=function5;
        Map_NamesOfFunctionsToActualFunctions["function6"]=function6;
        Map_NamesOfFunctionsToActualFunctions["function7"]=function7 ;
    
    
    
    
        GetControlFunctionNamesFromDiskFile();
    
    
        double x=1.0;
        cout << "Here x = 1.0" << endl;
        cout << "We selectively call only those functions whose names were written in the text file:" << endl;
        for( auto itr=vec_NamesOfFunctions.begin(), end=vec_NamesOfFunctions.end() ; itr != end; ++itr)
        { 
        if( Map_NamesOfFunctionsToActualFunctions.count(*itr) != 0 )
        {
                  Map_NamesOfFunctionsToActualFunctions[ *itr ]( x )  ;
        }
        else
        {
           cout << "Error: Function name missing from the map!" << endl;
        }
        }
        cout << "------------------------------------" << endl;
    
    
     }
    
    
     void GetControlFunctionNamesFromDiskFile(   )
    {
          string ControlParamFileFunctionsForFunctions = "FileForNamesOfFunctions.TXT";
          istringstream instream;   // Declare an input string stream
          ifstream inFile;
          string  firstStringOfLine;
          string s;
    
    
          inFile.open( ControlParamFileFunctionsForFunctions.c_str(), ios::in);
          if ( ! inFile.is_open() )
          {
                cout << "Could not open Key Text Input file!" << endl;
               exit(1);
          }
          while(  getline(inFile, s)  )
          {  
               instream.clear();
           instream.str(s);        
           instream >> firstStringOfLine;
               vec_NamesOfFunctions.push_back(firstStringOfLine);
          }
        
         inFile.close(); 
         cout << "The function names written in the disk file are: " << endl; 
         for( auto itr=vec_NamesOfFunctions.begin(), end =vec_NamesOfFunctions.end(); itr != end;  ++itr)
         {
              cout<<  *itr << endl; ;
         }
         cout << "---------------------------------------------" << endl; 
    
    
    }
    
    
    void function0(double x) {cout<<"function0 prints 0*x = " << 0*x << endl; }
    void function1(double x) {cout<<"function1 prints 1*x = " << 1*x << endl; }
    void function2(double x) {cout<<"function2 prints 2*x = " << 2*x << endl; }
    void function3(double x) {cout<<"function3 prints 3*x = " << 3*x << endl; }
    void function4(double x) {cout<<"function4 prints 4*x = " << 4*x << endl; }
    void function5(double x) {cout<<"function5 prints 5*x = " << 5*x << endl; }
    void function6(double x) {cout<<"function6 prints 6*x = " << 6*x << endl; }
    void function7(double x) {cout<<"function7 prints 7*x = " << 7*x << endl; }
    And here is the faulty output, which executes function6 4 times because the three blank lines in the text file caused the map to be filled with the same name an additional 3 times!! So there was an invisible character introduced in the text file when I used the return key!

    The function names written in the disk file are:
    function2
    function3
    function5
    function6
    function6
    function6
    function6
    ---------------------------------------------
    Here x = 1.0
    We selectively call only those functions whose names were written in the text file:
    function2 prints 2*x = 2
    function3 prints 3*x = 3
    function5 prints 5*x = 5
    function6 prints 6*x = 6
    function6 prints 6*x = 6
    function6 prints 6*x = 6
    function6 prints 6*x = 6


    How would you resolve this problem when reading the text file? The blank line actually caused the repetition of the function name, instead of just garbage.
    Last edited by FortranLevelC++; 06-19-2013 at 07:29 PM.

  5. #5
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81
    Quote Originally Posted by Neo1 View Post
    I don't know if this is a habit for you or not, but names such as these:

    Map_NamesOfFunctionsToActualFunctions
    ControlParamFileFunctionsForFunctions
    GetControlFunctionNamesFromDiskFile

    ..are way, way too long and overly descriptive, it's bordeline comical in this case.

    Map_NamesOfFunctionsToActualFunctions could easily just be "functions", "function_names", "fmap", "function_map" or so on, it adds nothing to the code, in fact it decreases readability and i imagine it is a pain to type out, or even remember.
    Many thanks, I am recovering from this habit. Because this program was originally for the audience here (some version was prevented a few weeks ago here), I tried to make it overly descriptive. I didn't mean to insult your intelligence, and it was the first time, and it was something new for me! I am used to for loops with indexes instead of iterators.
    Last edited by FortranLevelC++; 06-19-2013 at 07:19 PM.

  6. #6
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by FortranLevelC++ View Post
    Many thanks, I am recovering from this habit. Because this program was originally for the audience here (some version was prevented a few weeks ago here), I tried to make it overly descriptive. I didn't mean to insult your intelligence, and it was the first time, and it was something new for me! I am used to for loops with indexes instead of iterators.
    Insult my intelligence? Not at all. I find that the more code i read or write, the better i get at naming variables. I suggest moving away from camel case since it doesn't line up with the STL, but really it's a matter of taste.
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  7. #7
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81
    Quote Originally Posted by Neo1 View Post
    Insult my intelligence? Not at all. I find that the more code i read or write, the better i get at naming variables. I suggest moving away from camel case since it doesn't line up with the STL, but really it's a matter of taste.
    On this occasion, it seems that when we fill a map whose second argument is actually a function like this, there might be dangers, such as blank spaces before the function name entered after the operator "=".
    Code:
        Map_Functions["function1"]=function1;

  8. #8
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    On this occasion, it seems that when we fill a map whose second argument is actually a function like this, there might be dangers, such as blank spaces before the function name entered after the operator "=".
    O_o

    No. The problem you are seeing has nothing whatsoever to do with `std::map<???>'.

    You have committed the sin that most newbies make at some point: you've not validated your input.

    Think very carefully about what `GetControlFunctionNamesFromDiskFile' does for invalid input.

    *ping*

    *ping*

    *ping*

    No? Consider carefully that a blank line is still a "newline".

    *ping*

    *ping*

    *ping*

    Move the input around so a different function is the last listed before the blank lines.

    *ping*

    *ping*

    *ping*

    Okay. One last chance: do you know the return value of "stream operators"?

    *ping*

    *ping*

    *ping*

    I'll give you another hint.

    Soma

    Code:
    if(instream >> firstStringOfLine){/*returns `instream' */}

  9. #9
    Registered User FortranLevelC++'s Avatar
    Join Date
    May 2013
    Location
    United States
    Posts
    81
    Quote Originally Posted by phantomotap View Post
    O_o

    No. The problem you are seeing has nothing whatsoever to do with `std::map<???>'.

    You have committed the sin that most newbies make at some point: you've not validated your input.


    No? Consider carefully that a blank line is still a "newline".


    Code:
    if(instream >> firstStringOfLine){/*returns `instream' */}

    Many thanks. In other programs I have also added some more primitive safeguards, by putting the character '#' before any text line that contains parameters, to make sure that it is distinguished from blank lines...

    But separately, I have finally realized that the other problem was because I caused a segmentation error when some of the variables among so many (accumulating since the year 2007), started to conflict, and this was due to my poor version control of various files. Also, it seems to me that I should program less and study more C++ to learn the object-oriented system which I underestimated.

    In the past, I was using the Microsoft Visual C++ with the easy GUI editor that showed all the files included in the project, but recently I have started using g++ for Linux.

    What do you recommend for project management? I will definitely start using the makefiles to keep things organized, but do you use a GUI-based project management tool?

    I am also planning to learn QT to create GUI to control the programs in the Linux environment. What GUI system do you recommend for Linux? In the past used the Visual C++ to create some GUI, and it was deceptively easy due to the automated tools of Microsoft (traps to keep people ignorant.)
    Last edited by FortranLevelC++; 06-19-2013 at 10:38 PM.

  10. #10
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Also, it seems to me that I should program less and study more C++ to learn the object-oriented system which I underestimated.
    The easiest way to learn programming is to program. Keep choosing projects that you think are just at the limit of your capabilities, and you will pick up the rest along the way.

    As far as an IDE goes, try Code::Blocks.
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Neo1 View Post
    ...I suggest moving away from camel case since it doesn't line up with the STL, but really it's a matter of taste.
    Absolute nonsense. Naming convention is a matter of style. Just because something was written with some other style doesn't mean you aren't allowed to use anything else.
    Use whatever you are most comfortable with.

    Quote Originally Posted by FortranLevelC++ View Post
    What do you recommend for project management? I will definitely start using the makefiles to keep things organized, but do you use a GUI-based project management tool?
    Use whatever you like most. Some people like makefiles better than IDEs, and some are the reverse. It all comes down to what benefits you most for a given situation. Makefiles can probably do a little more than GUI tools, but are usually trickier and take more time to code and maintain. Good IDEs typically give all the necessary tools most of the time.
    So again, there is no best. Pick your poison.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by Elysia View Post
    Absolute nonsense. Naming convention is a matter of style. Just because something was written with some other style doesn't mean you aren't allowed to use anything else.
    Use whatever you are most comfortable with.
    It seems you are replying to the wrong post. I distincly remember saying "I suggest" and "it's a matter of taste", while you seem to be addressing some made up post where i said "i command you to" and "the dear leader has decreed: Thou shalt not use camelcase".
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Neo1 View Post
    It seems you are replying to the wrong post. I distincly remember saying "I suggest" and "it's a matter of taste", while you seem to be addressing some made up post where i said "i command you to" and "the dear leader has decreed: Thou shalt not use camelcase".
    You did mention:
    Quote Originally Posted by Neo1 View Post
    ]Insult my intelligence? Not at all. I find that the more code i read or write, the better i get at naming variables. I suggest moving away from camel case since it doesn't line up with the STL, but really it's a matter of taste.
    That is all that is needed. You should never suggest someone to move away from some naming convention. You may state that it is your opinion to do so to make it more clear that it is a suggestion, but frankly, I'd have done the same thing regardless. Giving people advice about not using CamelCase IMHO silly. Better spend your time and energy on moving people away from horrible styles.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Internet Superhero
    Join Date
    Sep 2006
    Location
    Denmark
    Posts
    964
    Quote Originally Posted by Elysia View Post
    You should never suggest someone to move away from some naming convention. You may state that it is your opinion to do so to make it more clear that it is a suggestion, but frankly, I'd have done the same thing regardless. Giving people advice about not using CamelCase IMHO silly. Better spend your time and energy on moving people away from horrible styles.
    We clearly have very different ideas about what constitutes a waste of time. I'd say this entire discussion is a waste of time but apparently you don't agree since you decided to start it. Anyways, i shall reserve my right to waste my time the way i see fit.

    Also, you should note that i _did_ give the OP a hint to move away from the rather horrible style that is on display in his first post, so with my quota of "spend your time and energy on moving people away from horrible styles" fulfilled for the day, i shall resume normal time-wasting activities (eg. replying to this inane meta-discussion)
    How I need a drink, alcoholic in nature, after the heavy lectures involving quantum mechanics.

  15. #15
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    That is all that is needed. You should never suggest someone to move away from some naming convention. You may state that it is your opinion to do so to make it more clear that it is a suggestion, but frankly, I'd have done the same thing regardless. Giving people advice about not using CamelCase IMHO silly. Better spend your time and energy on moving people away from horrible styles.
    O_o

    This from a person who has suggested on several occasions that other people bind themselves to using a C++11 compiler when the code in question would receive no benefit from C++11 features thus limiting the portability and available surface area without having a reason better than you personally like the C++11 features you are hocking?

    Interesting.

    In that spirit, you should never suggest someone move away from C++98; you should spend your time and energy moving people away from horrible C++98.

    The comment sounds silly doesn't it? There are perfectly good reasons to proselytize C++11 with care. There is nothing wrong with hocking a "one true style" either when "matter of taste" is laid on the table.

    Soma

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. static keyword in function declarations
    By memcpy in forum C Programming
    Replies: 2
    Last Post: 05-07-2012, 08:20 PM
  2. In .h files, should function declarations be 'extern' ?
    By Richardcavell in forum C Programming
    Replies: 2
    Last Post: 02-28-2011, 07:56 AM
  3. Function declarations
    By ssharish2005 in forum C Programming
    Replies: 9
    Last Post: 10-09-2007, 07:06 AM
  4. Weird function declarations
    By confuted in forum C Programming
    Replies: 6
    Last Post: 11-09-2005, 03:06 PM
  5. class function declarations
    By HSC140 in forum C++ Programming
    Replies: 4
    Last Post: 03-25-2002, 11:23 PM