Why does the order of my #includes matter? (C++) - c++

I've created a header file called "list_dec.h", put it in a folder "C:\Headers", and set my compiler to include files from "C:\Headers", so now I can do things like
#include<list_dec.h>
int main(){return(0);}
but when I try to do something like
#include<iostream>
#include<list_dec.h>
int main(){return(0);}
I get an error (not anything specific, just a huge list of syntax errors in "list_dec.h", which I know aren't real because I've been able to compile it as both a main.cpp file and a .h file in a separate project). However, when I change to order so "list_dec.h" is on top:
#include<list_dec.h>
#include<iostream>
int main(){return(0);}
all of the errors go away. So why does the order of the error matter?
NB: As far as I know, this occurs when I use "list_dec.h" with all header files, but the files I'm absolutely positive it occurs in are:
#include<iostream>
#include<vector>
#include<time.h>
#include<stdlib.h>
EDIT: These are the errors I get when "list_dec.h" is below any other header:
c:\headers\list_dec.h(14) : error C2143: syntax error : missing ')' before 'constant'
c:\headers\list_dec.h(51) : see reference to class template instantiation 'list<T,limit>' being compiled
c:\headers\list_dec.h(14) : error C2143: syntax error : missing ';' before 'constant'
c:\headers\list_dec.h(14) : error C2059: syntax error : ')'
c:\headers\list_dec.h(14) : error C2238: unexpected token(s) preceding ';'
c:\headers\list_dec.h(69) : warning C4346: 'list<T,limit>::{ctor}' : dependent name is not a type
prefix with 'typename' to indicate a type
c:\headers\list_dec.h(69) : error C2143: syntax error : missing ')' before 'constant'
c:\headers\list_dec.h(69) : error C2143: syntax error : missing ';' before 'constant'
c:\headers\list_dec.h(69) : error C2988: unrecognizable template declaration/definition
c:\headers\list_dec.h(69) : error C2059: syntax error : 'constant'
c:\headers\list_dec.h(69) : error C2059: syntax error : ')'
c:\headers\list_dec.h(78) : error C2065: 'T' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'limit' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'T' : undeclared identifier
c:\headers\list_dec.h(78) : error C2065: 'limit' : undeclared identifier
c:\headers\list_dec.h(79) : error C2143: syntax error : missing ';' before '{'
c:\headers\list_dec.h(79) : error C2447: '{' : missing function header (old-style formal list?)
If it helps, these are the lines mentioned in the errors (14, 69, 78, and 79):
Line 14: list(const T& NULL); (A constructor for "list" class)
Line 69: inline list<T, limit>::list(const T& NULL): (Definition for the constructor, also, the colon at the end is intentional, It part of the definion ie: void x(int n): VAR(n).)
Line 78: inline list<T, limit>::list(const list<T, limit>& lst) (def for the copy constructor)
Line 79: { (the begining of the list-copy contructor)
And a lot of people want to see the beginning of "list_dec.h":
template<class T, size_t limit>
class list
NB: These aren't the first lines, but they're where I think the problem is, the lines before them are simply an enumeration called "err".
EDIT: Just a note, "list_dec.h" contains no includes, defines, ifdefs, or anything precede with a '#'. Besides the enumeration, it only contains the "list" class declaration and the "list" class member function definitions.

Generally speaking it should not, however it may be possible for there to be conflicting definitions of symbols or preprocessor macros that end up confusing the compiler. Try to narrow down the size of the problem by removing pieces and includes from the conflicting header until you can see what is causing it.
In response to the error messages you posted, the symbol NULL is often implemented as a preprocessor macro for the number 0. This is so that you can easily use it as a null pointer. Therefore this:
list(const T& NULL);
Could be converted into this syntax error by the preprocessor:
list(const T& 0);
Change the name of the parameter to something other than NULL.

Note that here:
Line 14: list(const T& NULL); (A constructor for "list" class)
NULL is the name of standard macro - when a standard header file is included before list_dec.h it will most likely cause NULL to be defined which will in turn cause your code to look something like this to the compiler:
list(const T& 0);
The constant 0 above makes the line ill-formed C++. You might get more information by instructing your compiler to produce preprocessed output file.

Presumably list_dec.h is running into a macro that's defined in those other headers (or some headers they in turn include) -- hard to say which one without seeing the first error message and the relevant part of list_dec.h!

The actual errors would give a more specific clue, bt it means there's something in your include file that is screwing up the scan for the next one. The most common thing would be some kind of unclude #-directive, like a #if missing its #endif.

If the errors are random in nature, it could be a missing semi colon. The compiler will usually halt on that, but on occasion you get "lucky".
Otherwise, conflicting names or defines. Do you have anything named std for example?

Related

When im moving a class to a header file i get an error C++

Something annoying is going on here and I hope the community can help me :). My program is working correctly when I have my class in the cpp file. When I move my class code into a header file the program throws errors. Please instruct me. Thank you!
.cpp file
#include <iostream>
#include <string>
#include "CSquare.h"
using namespace std;
int main()
{
CSquare alo(1,"name");
}
CSquare.h
#pragma once
class CSquare
{
private:
int squareCode;
string squareName;
public:
CSquare(int, string);
void setCode(int);
void setName(string);
};
CSquare::CSquare(int inputSquareCode, string inputSquareName)
{
setCode(inputSquareCode);
setName(inputSquareName);
}
void CSquare::setCode(int inputSquareCode)
{
squareCode = inputSquareCode;
}
void CSquare::setName(string inputSquareName)
{
squareName = inputSquareName;
}
I have also tried moving the #include string in both files but still, nothing seems to fix the problem :/
error C3646: 'squareName': unknown override specifier error C4430: missing type specifier - int assumed. Note: C++ does not support default-int error C2061: syntax error: identifier 'string' C2061: syntax
error: identifier 'string' – Mash 16 mins ago
error C2061: syntax error: identifier 'string'
error C2065: 'inputSquareName': undeclared identifier
error C2065: 'string': undeclared identifier error C2146: syntax error: missing ')' before identifier 'inputSquareName'
error C2143: syntax
error: missing ';' before '{'
error C2447: '{': missing function header (old-style formal list?)
error C2661: 'CSquare::CSquare': no overloaded function takes 2 arguments –
CSquare.h lacks the definition for the type string.
Solution: Perhaps you intended to use std::string. In that case you must include <string> in CSquare.h and use the scope resolution operator to refer to the string declared in the std namespace. See the first sentence of this paragraph for an example.
CSquare.h contains definitions to non-inline functions. If the header is included in more than one translation unit, then you violate the one definition rule.
In the entire program, an object or non-inline function cannot have more than one definition
Solution: Either define the functions in a single source file, or declare the functions inline.

Declaration of templated class member function returning a map

In VC++ 2015 I have an untemplated class which should have a templated memberfunction which returns a map.
Here is a bit of the code:
class Registry
{
template<class configclass>
std::map<std::wstring, configclass> enumerateSubKeys(std::wstring subKeyName);
}
But the compiler throws error messages:
error C2988: Unrecognized template declaration/definition
error C2143: Syntax error: missing ";" before "<"
error C2238: Unexpected Token before ";"
error C2059: Syntax error: "<"
I assume my problem is in having to use a map where the wstring has to be fixed/untemplated but the second argument is my template class.
Of course i followed the compilers suggestions but that didn't get me any further.
You need to #include <map> and add a semi-colon to the end of your class declaration.
As #Kevin and #juanchopanza have pointed out in the comments, you are simply missing a semi-colon and potentially an include. With the following program in VS2013:
class Registry
{
template<class configclass>
std::map<std::wstring, configclass> enumerateSubKeys(std::wstring subKeyName);
}
int main()
{
}
I get an assortment of the errors you listed:
error C2143 : syntax error : missing ';' before '<'
error C2238 : unexpected token(s) preceding ';'
error C2988 : unrecognizable template declaration / definition
error C2059 : syntax error : '<'
And also:
error C2039 : 'map' : is not a member of 'std'
Once I add an include for std::map, the errors are reduced:
#include <map>
class Registry
{
template<class configclass>
std::map<std::wstring, configclass> enumerateSubKeys(std::wstring subKeyName);
}
error C2628 : 'Registry' followed by 'int' is illegal(did you forget a ';' ? )
Which suggests you are missing a semi-colon at the end of the class declaration.

if statement within namespace gives error

I have the following piece of C++ code which compiles without problem:
namespace namespace_top_of_FDD{
int int_systemReturn=system("pause | echo scope: namespace_top_of_FDD");
FDD*FDD_Ptr_Object=NULL;
//if(true){}
}
But when I add if statement, like the following, I get the following error massages, I'm wondering why.
namespace namespace_top_of_FDD{
int int_systemReturn=system("pause | echo scope: namespace_top_of_FDD");
FDD*FDD_Ptr_Object=NULL;
if(true){}
}
Error messages (when I use if statement):
1>.\FDD.cpp(6) : error C2059: syntax error : 'if'
1>.\FDD.cpp(6) : error C2143: syntax error : missing ';' before '{'
1>.\FDD.cpp(6) : error C2447: '{' : missing function header (old-style formal list?)
Code in namespaces may contain only declarations and/or definitions (which in turn are declarations). You may not place executable statements similar to the if statement.

VS2008 C++ "interface" as a parameter name fails to compile

As the title says, I'm getting a compiler error in a VS2008 C++ program. I'm not sure how better to describe my problem than in code. The following compiles unless I uncomment the TEST line.
#include <windows.h>
#include <iostream>
using namespace std;
//#define TEST //<-- uncomment for error
#ifdef TEST
void test(void* interface)
{
return;
}
#endif
int main()
{
cout << "Hello World" << endl;
system("PAUSE");
return(0);
}
When uncommented I get the following errors:
1>main.cpp(7) : error C2332: 'struct' : missing tag name
1>main.cpp(7) : error C2144: syntax error : '<unnamed-tag>' should be preceded by ')'
1>main.cpp(7) : error C2144: syntax error : '<unnamed-tag>' should be preceded by ';'
1>main.cpp(7) : error C2059: syntax error : ')'
1>main.cpp(8) : warning C4094: untagged 'struct' declared no symbols
1>main.cpp(8) : error C2143: syntax error : missing ';' before '{'
1>main.cpp(8) : error C2447: '{' : missing function header (old-style formal list?)
This is unmanaged code, so I'm not sure what the issue with the word interface is. Is there any way to get this code to compile as is, or do I have to change every instance of the term interface to something else?
Thanks!
If your code needs to include Windows.h then you should avoid using the name interface as it's reserved for the use that the Windows SDK has reserved for it (essentially it's a synonym for the keyword struct). There are probably hacks to work around that problem (you could #undef interface after including the SDK headers), but you should probably avoid using that identifier.
The word interface is reserved by MSVC++, as it is a non-standard keyword added by Microsoft Compiler, which is used to define interface in MSVC++.
So use a different name for the parameter, something like this:
#ifdef TEST
void test(void* test_interface)
{
return;
}
#endif

Templated function with two type parameters fails compile when used with an error-checking macro

Because someone in our group hates exceptions (let's not discuss that here), we tend to use error-checking macros in our C++ projects. I have encountered an odd compilation failure when using a templated function with two type parameters. There are a few errors (below), but I think the root cause is a warning:
warning C4002: too many actual parameters for macro 'BOOL_CHECK_BOOL_RETURN'
Probably best explained in code:
#include "stdafx.h"
template<class A, class B>
bool DoubleTemplated(B & value)
{
return true;
}
template<class A>
bool SingleTemplated(A & value)
{
return true;
}
bool NotTemplated(bool & value)
{
return true;
}
#define BOOL_CHECK_BOOL_RETURN(expr) \
do \
{ \
bool __b = (expr); \
if (!__b) \
{ \
return false; \
} \
} while (false) \
bool call()
{
bool thing = true;
// BOOL_CHECK_BOOL_RETURN(DoubleTemplated<int, bool>(thing));
// Above line doesn't compile.
BOOL_CHECK_BOOL_RETURN((DoubleTemplated<int, bool>(thing)));
// Above line compiles just fine.
bool temp = DoubleTemplated<int, bool>(thing);
// Above line compiles just fine.
BOOL_CHECK_BOOL_RETURN(SingleTemplated<bool>(thing));
BOOL_CHECK_BOOL_RETURN(NotTemplated(thing));
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
call();
return 0;
}
Here are the errors, when the offending line is not commented out:
1>------ Build started: Project: test, Configuration: Debug Win32 ------
1>Compiling...
1>test.cpp
1>c:\junk\temp\test\test\test.cpp(38) : warning C4002: too many actual parameters for macro 'BOOL_CHECK_BOOL_RETURN'
1>c:\junk\temp\test\test\test.cpp(38) : error C2143: syntax error : missing ',' before ')'
1>c:\junk\temp\test\test\test.cpp(38) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(41) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(48) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(49) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(52) : error C2143: syntax error : missing ';' before '}'
1>c:\junk\temp\test\test\test.cpp(54) : error C2065: 'argv' : undeclared identifier
1>c:\junk\temp\test\test\test.cpp(54) : error C2059: syntax error : ']'
1>c:\junk\temp\test\test\test.cpp(55) : error C2143: syntax error : missing ';' before '{'
1>c:\junk\temp\test\test\test.cpp(58) : error C2143: syntax error : missing ';' before '}'
1>c:\junk\temp\test\test\test.cpp(60) : error C2143: syntax error : missing ';' before '}'
1>c:\junk\temp\test\test\test.cpp(60) : fatal error C1004: unexpected end-of-file found
1>Build log was saved at "file://c:\junk\temp\test\test\Debug\BuildLog.htm"
1>test - 12 error(s), 1 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Any ideas? Thanks!
The preprocessor has no understanding of C++! It simply performs lexical substitutions.
When you declare a multi-argument macro, the arguments are separated by a comma. Since you have a comma in your macro invocation, you're calling the macro with multiple parameters, despite it being declared to only take one argument.
Parentheses are understood by the PP as forming a token group, so everything inside a set of parentheses is one big token.
Macros are unaware of the language, and work only with lexical tokens. A comma separates arguemnts for a macro, thus the following code attemps to 'invoke' the macro with two arguments:
BOOL_CHECK_BOOL_RETURN(DoubleTemplated<int, bool>(thing));
DoubleTemplated<int and bool>(thing). That's the warning you are seeing, and cause of the other errors as well. The following is the correct way to protect against , in template arguments list:
BOOL_CHECK_BOOL_RETURN((DoubleTemplated<int, bool>(thing)));
In the line that doesn't compile, that comma is interpreted by the preprocessor as a delimiter of the macro arguments.
In the C99 standard (I haven't got the C++ standard to hand, but it will be very similar), we see the following in section 6.10.3:
The sequence of preprocessing tokens bounded by the outside-most
matching parentheses forms the list of arguments for the function-like
macro. The individual arguments within the list are separated by comma
preprocessing tokens, but comma preprocessing tokens between matching
inner parentheses do not separate arguments.
So that's why your second macro instantiation works.