I'm writing some library and want to have some "optional" class methods (or just functions), declared or not, dependent on other library inclusion.
Say, I have a class SomeClass
with method int foo(std::string)
. Sometimes it's very useful to also have similar method(s) which uses classes of another library the project is build upon - for example, sf::String
or wxString
, for SFML or wxWidgets accordingly.
In this case including SFML/System.hpp
or even worse, wx/app.hpp
or similar is absolutely NOT an option, because I want to have only methods for libraries that are already included. So, my first example must (as I suppose) work fine, but it's not:
main.cpp:
#include <SFML/System.hpp> // FIRST, I include SFML base lib in the very first line.
#include <SFML/System/String.hpp>// to be 100% sure, I include SFML string class,
#include "a.h" // and ONLY AFTER that I include my own lib
// so inside the "a.h" file, the sf::String class *must* be already declared
main()
{ SomeClass x;
x.foo("ABC");// error here: "undefined reference to `SomeClass::foo(sf::String)"
}
a.h:
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
class SomeClass
{ public:
#ifdef SFML_STRING_HPP
int foo(sf::String str);// this method is declared, as expected
#endif
};
#endif
a.cpp:
#include "a.h"
#ifdef SFML_STRING_HPP
int SomeClass::foo(sf::String str)
{ return 1;
}
#endif
The first question is: WHY? a.cpp
includes a.h
in the very beginning, and inside a.h
the sf::String
is declared, so why inside a.cpp
after #include "a.h"
it is not declared in fact?
I've tried to add #error OK
right before #endif
directive in a.cpp
file, and this error is not fired.
Do I miss something about #include
and .cpp
/ .h
files?..
The second question is: How to fix that or work it around?
(And yes, I do a clean rebuild every time to avoid possible compiler bugs about partially changes sources, g likes it).
P.S: The same kind of "dependent" methods declarations works perfectly well with some template class - I suppose, it's because the implementation is within .h
file where everything is OK about conditional compilation.
CodePudding user response:
a.c includes a.h that does not include <SFML/System/String.hpp>, thus SFML_STRING_HPP is not defined. Usually, what to include is set through compiler -D options. For example -DUSE_SFML_STRING
main.cpp
#include <SFML/System.hpp> // FIRST, I include SFML base lib in the very first line.
#include "a.h" // and ONLY AFTER that I include my own lib
// so inside the "a.h" file, the sf::String class *must* be already declared
main()
{ SomeClass x;
x.foo("ABC");// error here: "undefined reference to `SomeClass::foo(sf::String)"
}
a.h
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
#ifdef USE_SFML_STRING
#include <SFML/System/String.hpp>
#endif
class SomeClass
{ public:
#ifdef SFML_STRING_HPP
int foo(sf::String str);// this method is declared, as expected
#endif
};
#endif