So, I had 2 files:
DFH_lib.h
Lib_Test.cpp
The programs were working perfectly just some 20-24 hours ago(I even have the executable file), I decided exclude the DFH_lib.cpp file as it is effectively empty (see below) and voila! It's giving me
Declaration Syntax Error
on the first line of the top template function.
I tried rearranging but it didn't help
This is super annoying, I'm stuck with Turbo because of my school and now this template based header file that I spend weeks building is suddenly not compiling.
Code
This is how the DFH_lib.h file starts (excluding the multi-line comment):
#ifndef DFH_lib_H
#define DFH_lib_H
enum bool { false, true };
template <class T> //Error on this line
void AddColumn(T data, const int& width) {
cout<<setw(width)<<data<<" | ";
}
NOTE: The error comes while compiling the DFH_lib.h
Question
On adding a DFH_lib.cpp file to the project, with nothing but this:
#ifndef _DFH_lib_CPP
#define _DFH_lib_CPP
#include"DFH_lib.h"
#if !defined __FSTREAM_H
#include<fstream.h>
#endif
#if !defined __IOMANIP_H
#include<iomanip.h>
#endif
#if !defined __CONIO_H
#include<conio.h>
#endif
#if !defined __STDIO_H
#include<stdio.h>
#endif
#if !defined __STRING_H
#include<string.h>
#endif
#endif
Everything worked fine! Why is this happening? All the headers written in DFH_lib.cpp are already included in the lib_Test.cpp prior to including DFH_lib.h.
In my opinion, the DFH_lib.cpp file is does nothing but it seems to be important none the less.
P.S. - I apologize if this is a duplicate, I know this question exists but I couldn't relate it to my situation. Here, the .cpp is effectively empty but still required.
A quick MCVE, that I put together:
UTILIZATION FILE:
#include<iostream.h>
#include<conio.h>
#include<iomanip.h>
#include"fileio.h"
void fillSpace(char ch, const int& width) {
cout<<setw(width)<<setfill(ch)<<"|";
}
int record_id = 1;
char char_member = 'A';
int int_member = 12;
float float_member = 2.3;
void show_tablular() {
cout<<endl; AddColumn(record_id,7); AddColumn(char_member, 20); AddColumn(int_member, 11); AddColumn(float_member, 13);
}
void main()
{
clrscr();
cout<<endl; AddColumn("Record", 7); AddColumn("Char Member", 20); AddColumn("Int Member", 11); AddColumn("Float Member", 13);
cout<<endl; AddColumn(" ", 7); AddColumn(" ", 20); AddColumn(" ", 11); AddColumn(" ", 13);
show_tablular();
cout<<endl; fillSpace('_', 7+2); fillSpace('_', 20+3); fillSpace('_', 11+3); fillSpace('_', 13+3);
cout<<setfill(' '); //Normalize cout based outputting format
getch();
}
IMPLEMENTATION FILE:
#include"fileio.h"
#if !defined __FSTREAM_H
#include<fstream.h>
#endif
#if !defined __IOMANIP_H
#include<iomanip.h>
#endif
#if !defined __CONIO_H
#include<conio.h>
#endif
#if !defined __STDIO_H
#include<stdio.h>
#endif
#if !defined __STRING_H
#include<string.h>
#endif
HEADER FILE:
#ifndef file_H
#define file_H
enum bool { false, true };
template <class T>
void AddColumn(T data, const int& width) {
cout<<setw(width)<<data<<" | ";
}
#endif
NOTE: They only work if added into a project in the same order from top to bottom otherwise the above error is encountered.
Related
Whenever I run the code it just comes out as what was put in the first .cpp file and ignores everything from the other one.
main.cpp:
#include <iostream>
#include "variables.h"
#include "intro.cpp"
using namespace std;
float gold;
int main()
{
float gold = 0;
intro();
cout<<gold;
return 0;
}
intro.cpp:
#include "variables.h"
void intro()
{
gold = 5.0;
}
header:
#ifndef VARIABLES_H_
#define VARIABLES_H_
extern float gold;
#endif
It always outputs gold as 0 instead of 5. What am I doing wrong?
int main()
{
float gold = 0;
...
cout<<gold;
}
You declared yet another variable gold, local, and print out it.
Remove the local variable declaration:
int main()
{
...
cout<<gold;
}
Or print out the global variable:
int main()
{
float gold = 0;
...
cout << ::gold;
}
I recommend you to read Why should I not include cpp files and instead use a header?
I have a problem with Visual Studio 2012 & 2015 about the fact than it's seem than the "ifndef" don't work. I use the "ifndef" for "NAN" and "ifndef" for the header file and it's said these 2 errors (see the image). When I add the link "#include"Outil.h"" in the header of other file, I see the same message of error.
I always do like this before and it's always work. I don’t understand why it's doesn't work now even with only two files.
I also try to change the name of the first function "realoc_ungraded" but it's doesn't work and I get the same error.
Message of error
The message:
1) Warning: C4005: 'NAN': macro redefinition of math.h
2) Error: LNK2005: "struct tab_dynamo __cdecl realoc_ugraded(struct tab_dynamo,unsigned int)" (?realoc_ugraded##YA?AUtab_dynamo##U1#I#Z) already defined in main.obj Project1
3) Error: LNK1169: one or more multiply defined symbols found Projet
There is the code of the different file:
File main.cpp
#include"Outil.h"
int main(void) {
return 0;
}
File Outil.h
#ifndef LIBRARY_OF_TOOLS
#define LIBRARY_OF_TOOLS 0
#define _USE_MATH_DEFINES
//NAN not defined in Visual Studio 2012, so I use the def. of VS 2015
#ifndef NAN
#define NAN ((float)(std::numeric_limits<float>::infinity*0.0F))
#endif
#include<iostream>
#include<string>
using namespace std;
#include<cmath>
#include<stdlib.h>
#include<stdio.h>
#include<assert.h>
#define ERROR_ADRESSE 0xcccccccc //default when not initialised
#define DEFAULT_LENGHT_TAB 1
//-----------------------------------------
typedef double type_data; //the type for calculation
//-----------------------------------------
/*Struct for my array*/
typedef struct {
type_data *tab;
unsigned int length;
}tab_dynamo;
//-----------------------------------------
template<typename T>
bool verify_ptr(const T *ptr) {
return (ptr == NULL || ptr == (T*)(ERROR_ADRESSE));
}
//-----------------------------------------
template<typename T>
void see_tab(const T *tab, const unsigned int taille) {
unsigned int i;
cout << endl << endl;
if (verify_ptr(tab) == false && taille > 0) {
cout << endl;
for (i = 0; i<taille; ++i) {
cout << tab[i] << "\t";
}
}
cout << endl << endl;
}
//-----------------------------------------
template<typename T>
T* realoc_ungraded(const T* original_tab, unsigned int *length, const unsigned int new_length) {
T* new_tab = NULL;
unsigned int precedent_length = 0, i;
/*1) Exception case to directly exit*/
if (new_length == 0) {
return NULL;
}
/*2) Verification of the ptr of the length*/
if (verify_ptr(length)) {
length = (unsigned int*)calloc(1, sizeof(unsigned int));
assert(length);
}
precedent_length = *length;
*length = new_length;
/*4) Creation of the new tab.*/
new_tab = (T*)calloc(*length, sizeof(T));
assert(new_tab);
/*5) To transfert data of the original tab to the new tab*/
if (precedent_length != 0 && verify_ptr(original_tab) == false) {
for (i = 0; i < precedent_length && i < new_length; ++i) {
new_tab[i] = original_tab[i];
}
}
return new_tab;
}
//-----------------------------------------
//Version with the use of the struct "tab_dynamo"
tab_dynamo realoc_ungraded(tab_dynamo original_tab, const unsigned int new_length) {
tab_dynamo tableau = { NULL, 0 };
tableau.tab = realoc_ugraded(original_tab.tab, &original_tab.length, new_length);
tableau.length = new_length;
return tableau;
}
#endif
File Outil.cpp:
#include"Outil.h"
#ifndef NAN
#define NAN ((float)(std::numeric_limits<float>::infinity*0.0F))
#endif
When preprocessor process these, the NAN is defined because it's not defined yet.
#include<cmath>
Then cmath maybe include math.h, and found NAN is defined by yours.
You can try to change the sequence of include and your definition.
#include <cmath>
#ifndef NAN
#define NAN ((float)(std::numeric_limits<float>::infinity*0.0F))
#endif
B.T.W If you compile using gcc, you could use -E option to see the output of preprocessor and know how the preprocess expand the macros.
The problem is that, when I set a breakpoint at the line of the #include, gdb just ignore the line and stop at the next instruction in the main (I compiled the main.cpp with g++ -g -O2 -std=c++11).
The program works perfect (-O2 doesn't affect the result at all), but I want to check what exactly does something inside that file, but I can't because gdb doesn't let me enter the code inside the file.
How can I debug code inside other file? Is it even possible?
Edit: Here is the code
main.cpp
#include <iostream>
#include <cstdlib>
#include <chrono>
#include "inc/includes.h"
template <class T>
void PrintVector(T* vector, int size){
for (int i=0; i<size; ++i){
std::cout << vector[i] << " ";
}
std::cout << std::endl;
}
template <class T>
void CheckTime(void (*f)(T*&, int), T* &vector, int size){
std::chrono::high_resolution_clock::time_point tantes, tdespues;
std::chrono::duration<double> transcurrido;
tantes = std::chrono::high_resolution_clock::now();
(*f)(vector, size);
tdespues = std::chrono::high_resolution_clock::now();
transcurrido = std::chrono::duration_cast<std::chrono::duration<double>(tdespues - tantes);
std::cout << size << " " << transcurrido.count() << std::endl;
}
int main(int argc, char * argv[]){
if (argc != 2){
std::cerr << "Formato " << argv[0] << " <num_elem>" << std::endl;
return -1;
}
int n = atoi(argv[1]);
int range;
#if defined RADIXSORTLSD || defined RADIXSORTMSD
unsigned short * array = new unsigned short[n];
range = (n<65536)?n:65536;
#else
unsigned int * array = new unsigned int[n];
range = n;
#endif
srand(time(0));
for (int i = 0; i < n; i++){
array[i] = rand()%range;
}
#ifdef PRINT
PrintVector(array, n);
#endif
#include "inc/select.h" //Here is the problem for debugging
#ifdef PRINT
PrintVector(array, n);
#endif
}
includes.h
#include "../src/radixsortlsd.cpp"
#include "../src/radixsortmsd.cpp"
#include "../src/mergesort.cpp"
#include "../src/bitonicsort.cpp"
#include "../src/insertion.cpp"
#include "../src/slowsort.cpp"
#include "../src/selection.cpp"
select.h This is the code I want to debug. I decided to separate it from the main because it will grow a lot.
// The calls to CheckTime takes the first parameter as the direction to a function, previously defined inside the cpps of includes.h
#ifdef RADIXSORTLSD
CheckTime(&RadixSortLSD, array, n);
#endif
#ifdef RADIXSORTMSD
CheckTime(&RadixSortMSD, array, n);
#endif
#ifdef MERGESORT
CheckTime(&MergeSort, array, n);
#endif
#ifdef INSERTION
CheckTime(&Insertion, array, n);
#endif
#ifdef SLOWSORT
CheckTime(&SlowSort, array, n);
#endif
#ifdef SELECTION
CheckTime(&Selection, array, n);
#endif
#ifdef BITONICSORT
CheckTime(&BitonicSort, array, n);
#endif
I hope this help. Note that everything compiles great and works great (I made sure that the macros I defined when compiling are the correct ones)
Note: By debugging (not the right word) I meant checking how a function works (a function I don't fully understand).
Possibly you could break at MyFunction(), then run 'bt' command to see the stack. Then you see, is there any additional stack frame or what stack frames consist of in terms of source files, it might help
First of all:
A include is a preprocessor directive which never generates code. Debuggers can stop only on things which can be executed. Including a file works during compilation, not during runtime.
The next:
Your included files will define some values, functions, classes and a lot other. So you must give the debugger an idea where to stop.
And at all:
Including 'cpp' files is really trash! There are only very seldom reasons to do this.
But ok, how to proceed:
If your header file ( or included cpp file ) provides a function, you simply can do a break Func and run your program. No need to open any file in a gui for gdb before.
If you want to look inside the included files, you also can list myheader.h:1. The 1 one is the line of code you want to start looking into the file.
And a hint: Please provide much smaller code examples which persons can compile for themselves to give you more detailed help. You example is really bad to understand!
Example session:
Header: f.h
#include <stdlib.h>
void g(void)
{
malloc(4000);
}
void f(void)
{
malloc(2000);
}
main.cpp:
#include "f.h"
int main(void)
{
int i;
int* a[10];
for (i = 0; i < 10; i++) {
a[i] = (int*)malloc(1000);
}
f();
g();
for (i = 0; i < 10; i++) {
free(a[i]);
return 0;
}
}
Example session:
> gdb prog
gdb) break f
Breakpoint 1 at 0x40061a: file main.cpp, line 10.
(gdb) run
Starting program: /home/xxx/go
Breakpoint 1, f () at f.h:10
10 malloc(2000);
(gdb) list
5 malloc(4000);
6 }
7
gdb )
Now you can walk through your subroutine with step.
Global.h
#ifndef GLOBAL_H
# define GLOBAL_H
#define DEBUG
#ifdef DEBUG
# define IF_DEBUG( ... ) __VA_ARGS__
#else
# define IF_DEBUG( ... )
#endif /* DEBUG */
#endif /* GLOBAL_H */
Main.cpp
#include <string>
#include <iostream>
#include "Global.h"
int main() {
int A = 1;
int B = 2;
int C = 0;
IF_DEBUG(
std::cout << "\nStep 1> Calculating...\n";
)
C = A + B;
// DO WHATEVER
IF_DEBUG(
std::cout << "\nStep n> ...\n";
)
// ...
std::cout << C << std::endl;
// Note: I could also do some operations within the IF_DEBUG macro.
IF_DEBUG(
int X = 10;
int Y = 5;
int Z = X / Y;
std::cout << Z << std::endl;
)
IF_DEBUG(
std::cout << "\nDebugged! This program has been paused. Enter any key to continue!\n";
::getchar();
)
return 0;
}
Do you see how I defined IF_DEBUG in the Global header file (Global.h) and how I constantly used
it in the Main source file (Main.cpp) for debugging purposes?
Is it okay and safe to do that?
I am asking this question because I am unsure if its okay to do that. When I show this to my friend and he said its "bad" to do that. Therefore, I am unsure.
This is a very common and useful trick. But it's better not to have the #define DEBUG in the source code. You can define it in the compile command line instead. g++ -DDEBUG -c file.cpp will compile the code as if DEBUG was defined.
If you're using a Makefile you can add it to the CPPFLAGS (C Preprocessor Flags) variable: CPPFLAGS=-DDEBUG.
If you're using an IDE try to find the C Preprocessor Flags in the project settings.
I can't understand how to embed C++ user-defined class into bison parser. Here is what I have (just some necessary pieces; if you need, I can post all code).
scanner.l
%{
#include "parser.tab.h"
#include "types.h"
#include <iostream>
#include <string>
#define YY_DECL extern "C" int yylex()
using namespace std;
int chars = 0;
int words = 0;
int lines = 0;
extern "C" {
int yylex(void);
} /* extern "C" */
%}
%%
"none" {
yylval.none_value = none_type();
return NONE;
} /* none type */
{DIGIT_BIN}|{DIGIT_OCT}|{DIGIT_DEC}|{DIGIT_HEX} {
yylval.int_value = atoi(yytext);
return INT;
} /* int type */
parser.y
%{
#include "types.h"
#include <iostream>
using namespace std;
void yyerror(const char *error) {
cerr << error << endl;
} /* error handler */
extern "C" {
int yylex(void);
int yyparse(void);
int yywrap() { return 1; }
} /* extern "C" */
%}
%union {
none_type none_value; /* HERE IS WHAT I WANT */
int int_value;
} /* union */
%token <none_value> NONE
%token <int_value> INT
types.h
#include <iostream>
class none_type {
public:
none_type(void);
~none_type();
}; /* none_type */
As you see the code here is not full, but it should be enough to describe what I want. Everything what I do with default C++ types works well; can I implement my own classes?
Compiler returns such errors:
parser.y:20:3: error: 'none_value' does not name a type
In file included from scanner.l:3:0:
parser.y:20:3: error: 'none_value' does not name a type
scanner.l: In function 'int yylex()':
scanner.l:54:32: error: cannot convert 'none_type' to 'int' in assignment
make: *** [caesar] Error 1
Thanks in advance!
When I compile your code with bison/g++ I get the errors:
parser.y:16:15: error: member ‘none_type YYSTYPE::none_value’ with constructor not allowed in union
parser.y:16:15: error: member ‘none_type YYSTYPE::none_value’ with destructor not allowed in union
parser.y:16:15: note: unrestricted unions only available with -std=c++0x or -std=gnu++0x
which tells you exactly what the problem is -- you can't put a non-POD type in a union, because the compiler can't tell which ctor/dtor to call for it. Note the comment that you CAN do it in C++ 11, but that doesn't really help, since in that case it won't call the ctor/dtor for you automatically, so stuff will simply not be cunstructed or destroyed properly.
If you want to play with putting genuine objects on your stack, then please, have a look at the current master branch of Bison, where you can run examples such as the following
%token <::std::string> TEXT;
%token <int> NUMBER;
%token END_OF_FILE 0;
%type <::std::string> item;
%type <::std::list<std::string>> list;
%printer { yyoutput << $$; } <int> <::std::string> <::std::list<std::string>>;
%%
result:
list { std::cout << $1 << std::endl; }
;
list:
/* nothing */ { /* Generates an empty string list */ }
| list item { std::swap ($$, $1); $$.push_back ($2); }
;
item:
TEXT { std::swap ($$, $1); }
| NUMBER { $$ = string_cast ($1); }
;
%%
// The yylex function providing subsequent tokens:
// TEXT "I have three numbers for you:"
// NUMBER 1
// NUMBER 2
// NUMBER 3
// TEXT " and that's all!"
// END_OF_FILE
static
yy::parser::symbol_type
yylex ()
{
static int stage = -1;
++stage;
yy::parser::location_type loc(0, stage + 1, stage + 1);
switch (stage)
{
case 0:
return yy::parser::make_TEXT ("I have three numbers for you.", loc);
case 1:
case 2:
case 3:
return yy::parser::make_NUMBER (stage, loc);
case 4:
return yy::parser::make_TEXT ("And that's all!", loc);
default:
return yy::parser::make_END_OF_FILE (loc);
}
}
Having opinions from possible users of this feature would be most useful. For instance on help-bison at gnu.org. See https://savannah.gnu.org/git/?group=bison for Git access to the repository.