Some of Qt classes require that QApplication must be constructed first. So, I wrote some code for calling singleton constructor in an appropriate place. Here is a "pure" C++ code for this.
#include <functional>
#include <iostream>
#include <list>
#define INITIALIZABLE(NAME) \
private: \
template <typename T> \
friend struct Initializer; \
inline static NAME* m_instance = nullptr; \
static void create() { m_instance = new NAME; } \
inline static Initializer<NAME> m_initializer{};
struct InitQueue {
static std::list<std::function<void(void)>>& getList()
{
static std::list<std::function<void(void)>> s_list;
return s_list;
}
};
template <class T>
struct Initializer {
Initializer()
{
auto initializer = []() {
T::create();
};
InitQueue::getList().push_back(initializer);
}
};
void initialize()
{
for (auto func : InitQueue::getList()) {
func();
}
}
class Foo {
INITIALIZABLE(Foo)
public:
Foo()
{
m_count++;
std::cout << "Ctor was called: " << m_count << "\n";
}
private:
static inline int m_count = 0;
};
int main(int, char**)
{
initialize();
return 0;
}
It worked as I expected. BUT then I make a Foo Inherited from QObject, somehow ctor of Foo is calling twice.
Foo.cpp
#include "Foo.hpp"
Foo::Foo(QObject* parent)
: QObject(parent)
{
m_count++;
std::cout << "Ctor was called: " << m_count << "\n";
}
std::list<std::function<void(void)>>& InitQueue::getList()
{
static std::list<std::function<void(void)>> s_list;
return s_list;
}
void initialize()
{
for (auto func : InitQueue::getList()) {
func();
}
}
Foo.hpp
#pragma once
#include <functional>
#include <iostream>
#include <list>
#include <qobject.h>
#define INITIALIZABLE(NAME) \
private: \
template <typename T> \
friend struct Initializer; \
inline static NAME* m_instance = nullptr; \
static void create() { m_instance = new NAME; } \
inline static Initializer<NAME> m_initializer{};
struct InitQueue {
static std::list<std::function<void(void)>>& getList();
};
template <class T>
struct Initializer {
Initializer()
{
auto initializer = []() {
T::create();
};
InitQueue::getList().push_back(initializer);
}
};
void initialize();
class Foo : public QObject {
INITIALIZABLE(Foo)
public:
Foo(QObject* parent = nullptr);
private:
static inline int m_count = 0;
};
main.cpp
#include "Foo.hpp"
int main(int, char**)
{
initialize();
std::cin.get();
return 0;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.12)
project(DoubleCtorCall)
set(CMAKE_CXX_STANDARD 17)
#Qt specific
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
#Qt
find_package(Qt5Core CONFIG REQUIRED)
set(SOURCES
Main.cpp Foo.cpp Foo.hpp)
add_executable(${PROJECT_NAME} ${SOURCES})
target_link_libraries(${PROJECT_NAME} Qt5::Core)
So. I have two questions: Why does this happened and how to avoid it (except once flags)?
Windows 10. MSVC 2017. Qt 5.12.
When you initialize static member variables in the header file, it is going to be initialized in each translation unit where the header is included.
In your case, m_initializer was initialized multiple times because Qt moc system generated some underlying files that include your "foo.h". Your InitQueue will contain multiple initializers that result in multiple calls to Foo Ctor.
Separating the variables defined in only one translation unit will help. For example :
#define ININIALIZEABLE(NAME) \
private: \
template <typename T> \
friend struct Initializer; \
static NAME* m_instance ; \
static void create() { m_instance = new NAME; } \
static Initializer<NAME> m_initializer;
#define IMPL_INITIALIZEABLE(NAME) \
NAME* NAME::m_instance = nullptr;\
Initializer<NAME> NAME::m_initializer{};
Then use the macro in your foo.cpp :
IMPL_INITIALIZEABLE(Foo)
Foo::Foo(QObject* parent)
: QObject(parent)
{
m_count++;
std::cout << "Ctor was called: " << m_count << "\n";
}
I can not answer the question directly. I can only be so bold to advise, that is not a "pure C++" code. I am using the following whenever I need "make it once and only once" standard C++, coding idiom:
// header only
// never anonymous namespace
namespace my_space
{
inline single_thing_type const & make_once
( /* if required arguments for initializaton go here */ )
{
auto initor_ = [&](){
/* this is where it is made */
static single_thing_type single_instance ;
/*
or calling some non-default ctor, or some factory
and doing whatever is required by single_thing_type
to be made and initialised
*/
return single_instance ;
};
/* this is resilient in presence of multiple threads */
static single_thing_type const & singleton_ = initor_() ;
/*
return by ref. so type can be
non-movable and non-copyable
if required
*/
return singleton_ ;
}
// here we can provide a process-wide global if required
inline single_thing_type const &
single_global_made_once = make_once () ;
} // my_space
There are many variations but this is the core of the idiom. I am sure it can be applied in the context of standard C++, using the Qt.
Not a Qt code bellow, is using the simplified still correct version of your class Foo from above:
namespace my_space
{
struct Foo {
Foo()
{
std::cout << "Foo() ctor called.\n";
}
}; // Foo
inline Foo const & make_once ( )
{
auto initor_ = [&](){
static Foo single_instance ;
return single_instance ;
};
static Foo const & singleton_ = initor_() ;
return singleton_ ;
}
inline Foo const &
single_global_foo_made_once = make_once () ;
} // my_space
int main ()
{
using namespace my_space;
auto const & it_is_already_made
= single_global_foo_made_once ;
}
I am not claiming I have invented this. For a good overview and details see here.
This idiom does not require the type handled, to be changed in any way. Perhaps you can try it on Qt types you need.
What is not in the so-called "Scot Meyers Singleton" is a use of the lambda ('initor' above). An good use case is creating a single instance of some event_log.
inline event_log const & const & make_event_log_once ( )
{
auto initor_ = [&](){
auto event_log_file_name
= read_it_from_environemnt_confif_or_whatever() ;
auto event_log_file_path
= ensure_platform_and_folder (event_log_file_name ) ;
return event_log( event_log_file_path ) ;
};
static event_log singleton_{ initor_() } ;
return singleton_ ;
}
inline event_log const &
event_log_instance = make_event_log_once () ;
Before we create the event log class instance we need to obtain the file name somehow and from somewhere. Then we need to make a full path form it, making sure platform is right and folder on that platform is assured. Just then we can make the instance of the event_log. This is what we do in the initor lambda, knowing all of that will be called only once.
Enjoy the standard C++
Related
Is it possible to get the object name too?
#include<cstdio>
class one {
public:
int no_of_students;
one() { no_of_students = 0; }
void new_admission() { no_of_students++; }
};
int main() {
one A;
for(int i = 0; i < 99; i++) {
A.new_admission();
}
cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
<<A.no_of_students<<" students";
}
where I can fetch the names, something like
[classname] = A.classname() = one
[objectname] = A.objectname() = A
Does C++ provide any mechanism to achieve this?
You can display the name of a variable by using the preprocessor. For instance
#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}
outputs
3one A
on my machine. The # changes a token into a string, after preprocessing the line is
std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";
Of course if you do something like
void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}
you will get
3one B
as the compiler doesn't keep track of all of the variable's names.
As it happens in gcc the result of typeid().name() is the mangled class name, to get the demangled version use
#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
one<int,one<double, int> > A;
int status;
char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
std::cout<<demangled<<"\t"<< quote(A) <<"\n";
free(demangled);
return 0;
}
which gives me
one<int, one<double, int> > A
Other compilers may use different naming schemes.
use typeid(class).name
// illustratory code assuming all includes/namespaces etc
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{};
int main(){
cout << typeid(A).name();
}
It is important to remember that this
gives an implementation defined names.
As far as I know, there is no way to get the name of the object at run time reliably e.g. 'A' in your code.
EDIT 2:
#include <typeinfo>
#include <iostream>
#include <map>
using namespace std;
struct A{
};
struct B{
};
map<const type_info*, string> m;
int main(){
m[&typeid(A)] = "A"; // Registration here
m[&typeid(B)] = "B"; // Registration here
A a;
cout << m[&typeid(a)];
}
To get class name without mangling stuff you can use func macro in constructor:
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
Do you want [classname] to be 'one' and [objectname] to be 'A'?
If so, this is not possible. These names are only abstractions for the programmer, and aren't actually used in the binary code that is generated. You could give the class a static variable classname, which you set to 'one' and a normal variable objectname which you would assign either directly, through a method or the constructor. You can then query these methods for the class and object names.
Just write simple template:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}
You could try using "typeid".
This doesn't work for "object" name but YOU know the object name so you'll just have to store it somewhere. The Compiler doesn't care what you namned an object.
Its worth bearing in mind, though, that the output of typeid is a compiler specific thing so even if it produces what you are after on the current platform it may not on another. This may or may not be a problem for you.
The other solution is to create some kind of template wrapper that you store the class name in. Then you need to use partial specialisation to get it to return the correct class name for you. This has the advantage of working compile time but is significantly more complex.
Edit: Being more explicit
template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};
Then for each class somethign liek the following:
template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};
Which could even be macro'd as follows:
#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \
Allowing you to, simply, do
DefineClassName( MyClass );
Finally to Get the class name you'd do the following:
ClassName< MyClass >::name();
Edit2: Elaborating further you'd then need to put this "DefineClassName" macro in each class you make and define a "classname" function that would call the static template function.
Edit3: And thinking about it ... Its obviously bad posting first thing in the morning as you may as well just define a member function "classname()" as follows:
std::string classname()
{
return "MyClass";
}
which can be macro'd as follows:
DefineClassName( className ) \
std::string classname() \
{ \
return #className; \
}
Then you can simply just drop
DefineClassName( MyClass );
into the class as you define it ...
You can try this:
template<typename T>
inline const char* getTypeName() {
return typeid(T).name();
}
#define DEFINE_TYPE_NAME(type, type_name) \
template<> \
inline const char* getTypeName<type>() { \
return type_name; \
}
DEFINE_TYPE_NAME(int, "int")
DEFINE_TYPE_NAME(float, "float")
DEFINE_TYPE_NAME(double, "double")
DEFINE_TYPE_NAME(std::string, "string")
DEFINE_TYPE_NAME(bool, "bool")
DEFINE_TYPE_NAME(uint32_t, "uint")
DEFINE_TYPE_NAME(uint64_t, "uint")
// add your custom types' definitions
And call it like that:
void main() {
std::cout << getTypeName<int>();
}
An improvement for #Chubsdad answer,
//main.cpp
using namespace std;
int main(){
A a;
a.run();
}
//A.h
class A{
public:
A(){};
void run();
}
//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
cout << (string)typeid(this).name();
}
Which will print:
class A*
Here is a trick for getting the name of a class you create:
struct NameTest {
NameTest() : mName {std::source_location::current().function_name()} {
}
void operator()() {
auto src_loc = std::source_location::current();
std::cout << "Class name:\t" << mName //
<< "\nFunc:\t\t" << src_loc.function_name() //
<< "\nLine:\t\t" << src_loc.line() << '\n';
}
const std::string mName;
};
int main() {
NameTest name_test;
name_test();
return 0;
}
output:
Class name: NameTest::NameTest()
Func: void NameTest::operator()()
Line: 81
A little string manipulation will strip the unneeded parts
Is it possible to get the object name too?
#include<cstdio>
class one {
public:
int no_of_students;
one() { no_of_students = 0; }
void new_admission() { no_of_students++; }
};
int main() {
one A;
for(int i = 0; i < 99; i++) {
A.new_admission();
}
cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
<<A.no_of_students<<" students";
}
where I can fetch the names, something like
[classname] = A.classname() = one
[objectname] = A.objectname() = A
Does C++ provide any mechanism to achieve this?
You can display the name of a variable by using the preprocessor. For instance
#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}
outputs
3one A
on my machine. The # changes a token into a string, after preprocessing the line is
std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";
Of course if you do something like
void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}
you will get
3one B
as the compiler doesn't keep track of all of the variable's names.
As it happens in gcc the result of typeid().name() is the mangled class name, to get the demangled version use
#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
one<int,one<double, int> > A;
int status;
char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
std::cout<<demangled<<"\t"<< quote(A) <<"\n";
free(demangled);
return 0;
}
which gives me
one<int, one<double, int> > A
Other compilers may use different naming schemes.
use typeid(class).name
// illustratory code assuming all includes/namespaces etc
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{};
int main(){
cout << typeid(A).name();
}
It is important to remember that this
gives an implementation defined names.
As far as I know, there is no way to get the name of the object at run time reliably e.g. 'A' in your code.
EDIT 2:
#include <typeinfo>
#include <iostream>
#include <map>
using namespace std;
struct A{
};
struct B{
};
map<const type_info*, string> m;
int main(){
m[&typeid(A)] = "A"; // Registration here
m[&typeid(B)] = "B"; // Registration here
A a;
cout << m[&typeid(a)];
}
To get class name without mangling stuff you can use func macro in constructor:
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
Do you want [classname] to be 'one' and [objectname] to be 'A'?
If so, this is not possible. These names are only abstractions for the programmer, and aren't actually used in the binary code that is generated. You could give the class a static variable classname, which you set to 'one' and a normal variable objectname which you would assign either directly, through a method or the constructor. You can then query these methods for the class and object names.
Just write simple template:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}
You could try using "typeid".
This doesn't work for "object" name but YOU know the object name so you'll just have to store it somewhere. The Compiler doesn't care what you namned an object.
Its worth bearing in mind, though, that the output of typeid is a compiler specific thing so even if it produces what you are after on the current platform it may not on another. This may or may not be a problem for you.
The other solution is to create some kind of template wrapper that you store the class name in. Then you need to use partial specialisation to get it to return the correct class name for you. This has the advantage of working compile time but is significantly more complex.
Edit: Being more explicit
template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};
Then for each class somethign liek the following:
template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};
Which could even be macro'd as follows:
#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \
Allowing you to, simply, do
DefineClassName( MyClass );
Finally to Get the class name you'd do the following:
ClassName< MyClass >::name();
Edit2: Elaborating further you'd then need to put this "DefineClassName" macro in each class you make and define a "classname" function that would call the static template function.
Edit3: And thinking about it ... Its obviously bad posting first thing in the morning as you may as well just define a member function "classname()" as follows:
std::string classname()
{
return "MyClass";
}
which can be macro'd as follows:
DefineClassName( className ) \
std::string classname() \
{ \
return #className; \
}
Then you can simply just drop
DefineClassName( MyClass );
into the class as you define it ...
You can try this:
template<typename T>
inline const char* getTypeName() {
return typeid(T).name();
}
#define DEFINE_TYPE_NAME(type, type_name) \
template<> \
inline const char* getTypeName<type>() { \
return type_name; \
}
DEFINE_TYPE_NAME(int, "int")
DEFINE_TYPE_NAME(float, "float")
DEFINE_TYPE_NAME(double, "double")
DEFINE_TYPE_NAME(std::string, "string")
DEFINE_TYPE_NAME(bool, "bool")
DEFINE_TYPE_NAME(uint32_t, "uint")
DEFINE_TYPE_NAME(uint64_t, "uint")
// add your custom types' definitions
And call it like that:
void main() {
std::cout << getTypeName<int>();
}
An improvement for #Chubsdad answer,
//main.cpp
using namespace std;
int main(){
A a;
a.run();
}
//A.h
class A{
public:
A(){};
void run();
}
//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
cout << (string)typeid(this).name();
}
Which will print:
class A*
Here is a trick for getting the name of a class you create:
struct NameTest {
NameTest() : mName {std::source_location::current().function_name()} {
}
void operator()() {
auto src_loc = std::source_location::current();
std::cout << "Class name:\t" << mName //
<< "\nFunc:\t\t" << src_loc.function_name() //
<< "\nLine:\t\t" << src_loc.line() << '\n';
}
const std::string mName;
};
int main() {
NameTest name_test;
name_test();
return 0;
}
output:
Class name: NameTest::NameTest()
Func: void NameTest::operator()()
Line: 81
A little string manipulation will strip the unneeded parts
I tried to do a fancy macro to have some debug informations: The name of the scope you currently are! This can be picked up by e.g. an assert. I tried to made it recursive:
// Global namespace
struct ScopeDef{ static const char* GetName() {return "";} };
typedef ScopeDef ScopeDefParent;
// Macro to place into your namespace/scope
#define NG_SCOPEDEF(scopename) \
struct ScopeDef { \
static const char* GetName() {return scopename;} \
typedef ScopeDefParent Parent; \
}; \
typedef ScopeDef ScopeDefParent;
And using it like:
// Recursive template for testing
template< class T > void PrintImpl() {
PrintImpl< T::Parent >();
printf("::%s", T::GetName() );
}
template<> void PrintImpl< ::ScopeDef >() {}
template< class T > void PrintS() { PrintImpl<T>(); printf("\n");}
// Lets try it:
namespace First {
NG_SCOPEDEF( "First" );
namespace Second {
NG_SCOPEDEF( "Second" );
static void AFun() {
// This prints "::First::Second"
PrintS<ScopeDef>();
}
}
struct Third {
NG_SCOPEDEF( "Third" );
static void BFun() {
// This is endless recursion
PrintS<ScopeDef>();
}
};
}
It doesn't work in class scopes, because the order of definitions don't matter.
This is not a good solution. So is there a way to access the parent scope in a way? In regular code I would just qualify ("::First::ScopeDef"), but that's nothing for a macro.
You could do something like this in C++, where you put in the macro whenever you open a scope and let the destructor take care of cleanup when the scope exits. This example will print out the full scope to stderr, and the output of this code is as follows.
main
main::First
main::First::Second
main::First::Second::DummyClass::DummyFunction
main::First
main
Here is the code:
#include <stdio.h>
class NG_SCOPE_CLASS;
NG_SCOPE_CLASS* NG_SCOPE_END = 0;
class NG_SCOPE_CLASS
{
public:
NG_SCOPE_CLASS(const char* scope)
{
_scope = scope;
_prev = NG_SCOPE_END;
NG_SCOPE_END = this;
}
~ NG_SCOPE_CLASS()
{
NG_SCOPE_END = _prev;
}
void PrintScope()
{
if(_prev)
{
_prev->PrintScope();
fprintf(stderr, "::");
}
fprintf(stderr, "%s", _scope);
}
private:
NG_SCOPE_CLASS* _prev;
const char* _scope;
};
#define NG_SCOPE_PRINT { if(NG_SCOPE_END) { NG_SCOPE_END->PrintScope(); fprintf(stderr, "\n"); } }
#define NG_SCOPE(X) NG_SCOPE_CLASS _NG_SCOPE_CLASS(X)
// THAT'S IT FOR THE DEFINITIONS ABOVE, BELOW IS JUST SOME SAMPLE CODE.
class DummyClass
{
public:
void DummyFunction()
{
NG_SCOPE("DummyClass::DummyFunction");
NG_SCOPE_PRINT;
}
};
int main(int argc, const char* argv[])
{
NG_SCOPE("main");
NG_SCOPE_PRINT;
{
NG_SCOPE("First");
NG_SCOPE_PRINT;
{
NG_SCOPE("Second");
NG_SCOPE_PRINT;
DummyClass theDummyInstance;
theDummyInstance.DummyFunction();
}
NG_SCOPE_PRINT;
}
NG_SCOPE_PRINT;
}
For completeness, our working solution:
#if defined(_MSC_VER)
// GCC solution below. Note MSVC gives warning about unused typedefs but can be suppressed.
#define NG_SCOPEDEF(scopename) \
struct ScopeDefTag { static const char* Name(){return (scopename);}; }; \
typedef ::Scopes::Impl< ScopeDefTag, ScopeDef > ScopeDefHelper; \
struct ScopeDef : ScopeDefHelper {}
#else
// GCC seems to not look ahead.
#define NG_SCOPEDEF(scopename) \
struct ScopeDefTag { static const char* Name(){return (scopename);}; struct SDH : ::Scopes::Impl< ScopeDefTag, ScopeDef >{}; }; \
struct ScopeDef : ScopeDefTag::SDH {}
#endif
namespace Scopes {
struct Chain {
const char* const m_Lit;
const Chain* const m_Prev;
Chain(const char* lit, const Chain* prev) :m_Lit(lit), m_Prev(prev) {}
};
template< bool DMY = true >
struct RootScopeDef
{
static const Chain chain;
static const Chain* Get() { return &chain; }
};
// Being template just to have this in header:
template< bool DMY > const Chain RootScopeDef<DMY>::chain = Chain( "", 0 );
template< class TAG, class PARENT >
struct Impl {
static const Chain chain;
static const Chain* Get() { return &chain; }
typedef PARENT Parent;
};
template< class TAG, class PARENT >
const Chain Impl<TAG, PARENT>::chain = Chain( TAG::Name(), &PARENT::chain );
} // namespace
// Global namespace
typedef Scopes::RootScopeDef<> ScopeDef;
It is based on loopholes in the compiler and is not standard compliant! MSVS thinks that the ScopeDef used as template argument isn't the following one, since it is depending on that very typedef, so it resolves to the parent one, which will be shadowed after. This also works when the macro is placed in a template, because MSVS instantiates them lazily. GCC instead seems to just not look ahead and resolves the base of SDH to the correct one. MSVS would produce an infinite loop of m_Prev references here.
Bottom line: this gives you a nice way to print out namespaces and classes for debugging purposes, but also serves as types for e.g. specializations of templates!
My current implementation, simplified:
#include <string>
#include <memory>
class Log
{
public:
~Log() {
// closing file-descriptors, etc...
}
static void LogMsg( const std::string& msg )
{
static std::unique_ptr<Log> g_singleton;
if ( !g_singleton.get() )
g_singleton.reset( new Log );
g_singleton->logMsg( msg );
}
private:
Log() { }
void logMsg( const std::string& msg ) {
// do work
}
};
In general, I am satisfied with this implementation because:
lazy instantiation means I don't pay unless I use it
use of unique_ptr means automatic cleanup so valgrind is happy
relatively simple, easy-to-understand implementation
However, the negatives are:
singletons aren't conducive to unit-testing
dissonance in the back of my mind for introducing a pseudo-global (a bit of a code smell)
So here are my questions directed towards those developers who are successful in exorcising all singletons from their C++ code:
What kind of non-Singleton implementation do you use for application-wide logging?
Is the interface as simple and accessible as a Log::LogMsg() call above?
I want to avoid passing a Log instance all over my code, if at all possible - note: I am asking because, I, too, want to exorcise all Singletons from my code if there is a good, reasonable alternative.
First: the use of std::unique_ptr is unnecessary:
void Log::LogMsg(std::string const& s) {
static Log L;
L.log(s);
}
Produces exactly the same lazy initialization and cleanup semantics without introducing all the syntax noise (and redundant test).
Now that is out of the way...
Your class is extremely simple. You might want to build a slightly more complicated version, typical requirements for log messages are:
timestamp
level
file
line
function
process name / thread id (if relevant)
on top of the message itself.
As such, it is perfectly conceivable to have several objects with different parameters:
// LogSink is a backend consuming preformatted messages
// there can be several different instances depending on where
// to send the data
class Logger {
public:
Logger(Level l, LogSink& ls);
void operator()(std::string const& message,
char const* function,
char const* file,
int line);
private:
Level _level;
LogSink& _sink;
};
And you usually wrap the access inside a macro for convenience:
#define LOG(Logger_, Message_) \
Logger_( \
static_cast<std::ostringstream&>( \
std::ostringstream().flush() << Message_ \
).str(), \
__FUNCTION__, \
__FILE__, \
__LINE__ \
);
Now, we can create a simple verbose logger:
Logger& Debug() {
static Logger logger(Level::Debug, Console);
return logger;
}
#ifdef NDEBUG
# define LOG_DEBUG(_) do {} while(0)
#else
# define LOG_DEBUG(Message_) LOG(Debug(), Message_)
#endif
And use it conveniently:
int foo(int a, int b) {
int result = a + b;
LOG_DEBUG("a = " << a << ", b = " << b << " --> result = " << result)
return result;
}
The purpose of this rant ? Not all that is a global need be unique. The uniqueness of Singletons is generally useless.
Note: if the bit of magic involving std::ostringstream scares you, this is normal, see this question
I'd go with the simple, pragmatic solution:
you want a solution that is globally accessible. For the most part, I try to avoid globals, but for loggers, let's face it, it's usually impractical.
So, we do need something to be globally accessible.
But, we don't want the additional "there can be only one" restriction that a singleton confers. Some of your unit tests might want to instantiate their own private logger. Others might want to replace the global logger, perhaps.
So make it a global. A plain old simple global variable.
This still doesn't fully solve the problem with unit testing, admittedly, but we can't always have everything we want. ;)
As pointed out in the comment, you need to consider the initialization order for globals, which, in C++, is partly undefined.
In my code, that is generally not a problem, because I rarely have more than one global (my logger), and I stick rigidly to a rule of never allowing globals to depend on each others.
But it's something you have to consider, at least.
I really like the following interface since it uses streaming. Of course you can add channels, time and thread information to it. Another possible extension is to use the __FILE__ and __LINE__ macros and add it as parameters to the constructor. You could even add a variadic template function if you do not like the stream syntax. If you want to store some configuration you could add them to some static variables.
#include <iostream>
#include <sstream>
class LogLine {
public:
LogLine(std::ostream& out = std::cout) : m_Out(out) {}
~LogLine() {
m_Stream << "\n";
m_Out << m_Stream.rdbuf();
m_Out.flush();
}
template <class T>
LogLine& operator<<(const T& thing) { m_Stream << thing; return *this; }
private:
std::stringstream m_Stream;
std::ostream& m_Out;
//static LogFilter...
};
int main(int argc, char *argv[])
{
LogLine() << "LogLine " << 4 << " the win....";
return 0;
}
// file ILoggerImpl.h
struct ILoggerImpl
{
virtual ~ILoggerImpl() {}
virtual void Info(std::string s) = 0;
virtual void Warning(std::string s) = 0;
virtual void Error(std::string s) = 0;
};
// file logger.h //
#include "ILoggerImpl.h"
class CLogger: public ILoggerImpl
{
public:
CLogger():log(NULL) { }
//interface
void Info(std::string s) {if (NULL==log) return; log->Info(s); }
void Warning(std::string s) {if (NULL==log) return; log->Warning(s); }
void Error(std::string s) {if (NULL==log) return; log->Error(s); }
//
void BindImplementation(ILoggerImpl &ilog) { log = &ilog; }
void UnbindImplementation(){ log = NULL; }
private:
ILoggerImpl *log;
};
// file: loggers.h //
#include "logger.h"
extern CLogger Log1;
extern CLogger Log2;
extern CLogger Log3;
extern CLogger Log4;
extern CLogger LogB;
/// file: A.h //
#include "loggers.h"
class A
{
public:
void foo()
{
Log1.Info("asdhoj");
Log2.Info("asdhoj");
Log3.Info("asdhoj");
}
private:
};
/// file: B.h //
#include "loggers.h"
class B
{
public:
void bar()
{
Log1.Info("asdhoj");
Log2.Info("asdhoj");
LogB.Info("asdhoj");
a.foo();
}
private:
A a;
};
////// file: main.cpp ////////////////
#include "loggers.h"
#include "A.h"
#include "B.h"
#include "fileloger.h"
#include "xmllogger.h"
CLogger Log1;
CLogger Log2;
CLogger Log3;
CLogger Log4;
CLogger LogB;
// client code
int main()
{
std::unique_ptr<ILoggerImpl> filelog1(new CFileLogger("C:\\log1.txt"));
Log1.BindImplementation(*filelog1.get());
std::unique_ptr<ILoggerImpl> xmllogger2(new CXmlLogger("C:\\log2.xml"));
Log2.BindImplementation(*xmllogger2.get());
std::unique_ptr<ILoggerImpl> xmllogger3(new CXmlLogger("C:\\logB.xml"));
LogB.BindImplementation(*xmllogger3.get());
B b;
b.bar();
return 0;
};
// testing code
///////file: test.cpp /////////////////////////////////
#include "loggers.h"
CLogger Log1;
CLogger Log2;
CLogger Log3;
CLogger Log4;
int main()
{
run_all_tests();
}
///////file: test_a.cpp /////////////////////////////////
#include "A.h"
TEST(test1)
{
A a;
}
TEST(test2, A_logs_to_Log1_when_foo_is_called())
{
A a;
std::unique_ptr<ILoggerImpl> filelog1Mock(new CFileLoggerMock("C:\\log1.txt"));
Log1.BindImplementation(*filelog1.get());
EXPECT_CALL(filelog1Mock Info...);
a.foo();
Log1.UnbindImplementation();
}
Is it possible to get the object name too?
#include<cstdio>
class one {
public:
int no_of_students;
one() { no_of_students = 0; }
void new_admission() { no_of_students++; }
};
int main() {
one A;
for(int i = 0; i < 99; i++) {
A.new_admission();
}
cout<<"class"<<[classname]<<" "<<[objectname]<<"has "
<<A.no_of_students<<" students";
}
where I can fetch the names, something like
[classname] = A.classname() = one
[objectname] = A.objectname() = A
Does C++ provide any mechanism to achieve this?
You can display the name of a variable by using the preprocessor. For instance
#include <iostream>
#define quote(x) #x
class one {};
int main(){
one A;
std::cout<<typeid(A).name()<<"\t"<< quote(A) <<"\n";
return 0;
}
outputs
3one A
on my machine. The # changes a token into a string, after preprocessing the line is
std::cout<<typeid(A).name()<<"\t"<< "A" <<"\n";
Of course if you do something like
void foo(one B){
std::cout<<typeid(B).name()<<"\t"<< quote(B) <<"\n";
}
int main(){
one A;
foo(A);
return 0;
}
you will get
3one B
as the compiler doesn't keep track of all of the variable's names.
As it happens in gcc the result of typeid().name() is the mangled class name, to get the demangled version use
#include <iostream>
#include <cxxabi.h>
#define quote(x) #x
template <typename foo,typename bar> class one{ };
int main(){
one<int,one<double, int> > A;
int status;
char * demangled = abi::__cxa_demangle(typeid(A).name(),0,0,&status);
std::cout<<demangled<<"\t"<< quote(A) <<"\n";
free(demangled);
return 0;
}
which gives me
one<int, one<double, int> > A
Other compilers may use different naming schemes.
use typeid(class).name
// illustratory code assuming all includes/namespaces etc
#include <iostream>
#include <typeinfo>
using namespace std;
struct A{};
int main(){
cout << typeid(A).name();
}
It is important to remember that this
gives an implementation defined names.
As far as I know, there is no way to get the name of the object at run time reliably e.g. 'A' in your code.
EDIT 2:
#include <typeinfo>
#include <iostream>
#include <map>
using namespace std;
struct A{
};
struct B{
};
map<const type_info*, string> m;
int main(){
m[&typeid(A)] = "A"; // Registration here
m[&typeid(B)] = "B"; // Registration here
A a;
cout << m[&typeid(a)];
}
To get class name without mangling stuff you can use func macro in constructor:
class MyClass {
const char* name;
MyClass() {
name = __func__;
}
}
Do you want [classname] to be 'one' and [objectname] to be 'A'?
If so, this is not possible. These names are only abstractions for the programmer, and aren't actually used in the binary code that is generated. You could give the class a static variable classname, which you set to 'one' and a normal variable objectname which you would assign either directly, through a method or the constructor. You can then query these methods for the class and object names.
Just write simple template:
template<typename T>
const char* getClassName(T) {
return typeid(T).name();
}
struct A {} a;
void main() {
std::cout << getClassName(a);
}
You could try using "typeid".
This doesn't work for "object" name but YOU know the object name so you'll just have to store it somewhere. The Compiler doesn't care what you namned an object.
Its worth bearing in mind, though, that the output of typeid is a compiler specific thing so even if it produces what you are after on the current platform it may not on another. This may or may not be a problem for you.
The other solution is to create some kind of template wrapper that you store the class name in. Then you need to use partial specialisation to get it to return the correct class name for you. This has the advantage of working compile time but is significantly more complex.
Edit: Being more explicit
template< typename Type > class ClassName
{
public:
static std::string name()
{
return "Unknown";
}
};
Then for each class somethign liek the following:
template<> class ClassName<MyClass>
{
public:
static std::string name()
{
return "MyClass";
}
};
Which could even be macro'd as follows:
#define DefineClassName( className ) \
\
template<> class ClassName<className> \
{ \
public: \
static std::string name() \
{ \
return #className; \
} \
}; \
Allowing you to, simply, do
DefineClassName( MyClass );
Finally to Get the class name you'd do the following:
ClassName< MyClass >::name();
Edit2: Elaborating further you'd then need to put this "DefineClassName" macro in each class you make and define a "classname" function that would call the static template function.
Edit3: And thinking about it ... Its obviously bad posting first thing in the morning as you may as well just define a member function "classname()" as follows:
std::string classname()
{
return "MyClass";
}
which can be macro'd as follows:
DefineClassName( className ) \
std::string classname() \
{ \
return #className; \
}
Then you can simply just drop
DefineClassName( MyClass );
into the class as you define it ...
You can try this:
template<typename T>
inline const char* getTypeName() {
return typeid(T).name();
}
#define DEFINE_TYPE_NAME(type, type_name) \
template<> \
inline const char* getTypeName<type>() { \
return type_name; \
}
DEFINE_TYPE_NAME(int, "int")
DEFINE_TYPE_NAME(float, "float")
DEFINE_TYPE_NAME(double, "double")
DEFINE_TYPE_NAME(std::string, "string")
DEFINE_TYPE_NAME(bool, "bool")
DEFINE_TYPE_NAME(uint32_t, "uint")
DEFINE_TYPE_NAME(uint64_t, "uint")
// add your custom types' definitions
And call it like that:
void main() {
std::cout << getTypeName<int>();
}
An improvement for #Chubsdad answer,
//main.cpp
using namespace std;
int main(){
A a;
a.run();
}
//A.h
class A{
public:
A(){};
void run();
}
//A.cpp
#include <iostream>
#include <typeinfo>
void A::run(){
cout << (string)typeid(this).name();
}
Which will print:
class A*
Here is a trick for getting the name of a class you create:
struct NameTest {
NameTest() : mName {std::source_location::current().function_name()} {
}
void operator()() {
auto src_loc = std::source_location::current();
std::cout << "Class name:\t" << mName //
<< "\nFunc:\t\t" << src_loc.function_name() //
<< "\nLine:\t\t" << src_loc.line() << '\n';
}
const std::string mName;
};
int main() {
NameTest name_test;
name_test();
return 0;
}
output:
Class name: NameTest::NameTest()
Func: void NameTest::operator()()
Line: 81
A little string manipulation will strip the unneeded parts