I'm having problem in splitting a code into .h
and .ccp
files.
Here is the main.cpp
:
#include <iostream>
#include "con_colour.h"
int main()
{
std::cout << setcolour(GREEN) << "Hello world!";
return 0;
}
And here is the monolithic con_colour.h
file which works fine:
#ifndef CON_COLOUR_H
#define CON_COLOUR_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <ios>
enum Colour { BLACK=0x00, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED,
DARK_PURPLE, DARK_YELLOW, WHITE, GRAY, BLUE, GREEN,
AQUA, RED, PURPLE, YELLOW, BRIGHT };
struct _colour_struct
{
uint8_t _colour_code;
};
// This function is used to set colour attributes
inline _colour_struct setcolour (Colour colour_foregrnd, Colour colour_backgrnd =BLACK)
{
uint8_t colour_code = colour_backgrnd;
colour_code <<= 4;
colour_code |= colour_foregrnd;
return { colour_code };
}
namespace std
{
template<typename _CharT, typename _Traits>
// Overloading the operator<< of ostream for changing the colour attributes
inline basic_ostream<_CharT, _Traits>&
operator<<(basic_ostream<_CharT, _Traits>& __os, _colour_struct __col)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), __col._colour_code);
return __os;
}
}
char blank_char = ' '; // To be printed where console wants to show an empty cell.
COORD home = {0,0}; // The return position of cursor after clearing a screen.
// This function should be used to clear the screen instead of other methods.
bool ClearScreen (Colour colour_backgrnd =BLACK)
{
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
DWORD buffer_size = csbi.dwSize.X * csbi.dwSize.Y;
DWORD chars_written;
FillConsoleOutputCharacter(hStdOut, blank_char, buffer_size, home, &chars_written);
DWORD attribs_written;
FillConsoleOutputAttribute(hStdOut, colour_backgrnd<<4, buffer_size,
home, &attribs_written);
SetConsoleCursorPosition(hStdOut, home);
return chars_written == buffer_size && attribs_written == buffer_size;
}
// This one clears only the currently visible_through_window portion of the buffer.
bool ClearVisibleScreen (Colour colour_backgrnd =BLACK)
{
// edited out for brevity
}
Colour GetForegrndColour ()
{
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo(hStdOut, &csbi);
uint8_t full_colour_code = csbi.wAttributes;
uint8_t foregrnd_colour_code = full_colour_code & 0x0F;
return static_cast<Colour>(foregrnd_colour_code);
}
Colour GetBackgrndColour ()
{
// edited out for brevity
}
#ifdef CON_COLOUR_MIXMATCH
#include <cctype>
// Just a small Utility to mix-match and explore nice colour combinations
void ColourMixMatch ()
{
// edited out for brevity
}
#endif // CON_COLOUR_MIXMATCH
#endif //CON_COLOUR_H
Now let's split it into a .h
and a .cpp
:
con_colour.h
#ifndef CON_COLOUR_H
#define CON_COLOUR_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include <ios>
enum Colour { BLACK=0x00, DARK_BLUE, DARK_GREEN, DARK_AQUA, DARK_RED,
DARK_PURPLE, DARK_YELLOW, WHITE, GRAY, BLUE, GREEN,
AQUA, RED, PURPLE, YELLOW, BRIGHT };
struct _colour_struct
{
uint8_t _colour_code;
};
// This function is used to set colour attributes
_colour_struct setcolour (Colour colour_foregrnd, Colour colour_backgrnd =BLACK);
namespace std
{
template<typename _CharT, typename _Traits>
// Overloading the operator<< of ostream for changing the colour attributes
basic_ostream<_CharT, _Traits>&
operator<<( basic_ostream<_CharT, _Traits>& __os, _colour_struct __col );
}
// This function is used to get the current foreground colour
Colour GetForegrndColour ();
// This function is used to get the current background colour
Colour GetBackgrndColour ();
char blank_char = ' '; // To be printed where console wants to show an empty cell.
COORD home = {0,0}; // The return position of cursor after clearing a screen.
// This function should be used to clear the screen instead of other methods.
bool ClearScreen (Colour colour_backgrnd =BLACK);
#ifdef CON_COLOUR_MIXMATCH
#include <cctype>
// Just a small Utility to mix-match and explore nice colour combinations
void ColourMixMatch ();
#endif // CON_COLOUR_MIXMATCH
#endif //CON_COLOUR_H
con_colour.cpp
#include "con_colour.h"
inline _colour_struct setcolour (Colour colour_foregrnd, Colour colour_backgrnd)
{
uint8_t colour_code = colour_backgrnd;
colour_code <<= 4;
colour_code |= colour_foregrnd;
return { colour_code };
}
namespace std
{
template<typename _CharT, typename _Traits>
// Overloading the operator<< of ostream for changing the colour attributes
inline basic_ostream<_CharT, _Traits>&
operator<<( basic_ostream<_CharT, _Traits>& __os, _colour_struct __col )
{
SetConsoleTextAttribute( GetStdHandle(STD_OUTPUT_HANDLE), __col._colour_code );
return __os;
}
}
Colour GetForegrndColour ()
{
// edited out for brevity
}
Colour GetBackgrndColour ()
{
// edited out for brevity
}
bool ClearScreen (Colour colour_backgrnd)
{
// edited out for brevity
}
#ifdef CON_COLOUR_MIXMATCH
void ColourMixMatch ()
{
// edited out for brevity
}
#endif // CON_COLOUR_MIXMATCH
When I try the split version, I get
from "Build Log" of CodeBlocks:
[Edited out the long paths of files]
g++.exe -g -DDEBUG_TEMPLATE_BASED_EXTRACTION -Winline -pedantic -Wextra -std=c++11 -m32 -c ".\con_colour.cpp" -o .\con_colour.o
g++.exe -g -DDEBUG_TEMPLATE_BASED_EXTRACTION -Winline -pedantic -Wextra -std=c++11 -m32 -c ".\main.cpp" -o .\main.o
g++.exe -o .\test.exe .\con_colour.o .\main.o -m32 -static-libgcc -static-libstdc++
.\main.o:main.cpp:(.data+0x0): multiple definition of `blank_char'
.\con_colour.o:con_colour.cpp:(.data+0x0): first defined here
.\main.o: In function `main':
.\main.cpp:10: multiple definition of `home'
.\con_colour.o:con_colour.cpp:24: first defined here
.\main.o:main.cpp:(.text+0x26): undefined reference to `setcolour(Colour, Colour)'
.\main.o:main.cpp:(.text+0x36): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, _colour_struct)'
collect2.exe: error: ld returned 1 exit status
from "Build Messages" of CodeBlocks:
| main.o | | In function `main': |
| main.cpp | 10| multiple definition of `home' |
| con_colour.o:con_colour.cpp| 24| first defined here |
| main.o:main.cpp | | undefined reference to `setcolour(Colour, Colour)' |
| main.o:main.cpp | | undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, _colour_struct)'|
error: ld returned 1 exit status
NOTE:
How it started: I was working on some other project and the monolithic .h version emitted errors of multiple definitions. Both definitions pointed to the same function in the .h. So, clearly, the same functions are being detected twice by the g++. So I thought that maybe splitting it into .h and .cpp will solve it. But it started emitting whole another kind of errors. So I thought of indepently checking the con_colour. And it won't compile...
Aucun commentaire:
Enregistrer un commentaire