samedi 20 février 2021

Linking error related to templates in C++ [duplicate]

I am trying to write a logger with one logger class and another functor class to use the logger. Although the logger class can be used directly(I am able to build it), but the functor is not building. I have tried moving the templated function implementations into the header files, but same error is there. I read somewhere that the templates have to be kept in headers. I have the following code:

LoggerImpl.cpp

#include "LoggerImpl.h"
#include <string>

LoggerImpl::LoggerImpl()
{
}
LoggerImpl* LoggerImpl::getInstance()
{
        std::lock_guard<std::mutex> lock(_loggerMutex);
        if(_instance == nullptr)
        {
                _instance = new LoggerImpl();
        }
        return _instance;
}

std::string LoggerImpl::_getCurrentTimestamp()
{
        
        return currentTime;
}

template<typename T>
void LoggerImpl::_logger(loglevel level, const T& message, const std::string& logFile)
{
        std::string levelStr;
        if(level == loglevel::trace)
                levelStr = "TRACE";
        if(level == loglevel::debug)
                levelStr = "DEBUG";
        if(level == loglevel::error)
                levelStr = "ERROR";
        {
                std::lock_guard<std::mutex> lock(_loggingMutex);
                std::cout << "[" <<_getCurrentTimestamp() << ":" << levelStr << "] "<< message << std::endl;
        }
}

template<typename T>
void LoggerImpl::trace(const T&  message, const std::string& logFile)
{
        _logger(loglevel::trace, message, logFile);
}

template<typename T>
void LoggerImpl::debug(const T&  message, const std::string& logFile)
{
        _logger(loglevel::debug, message, logFile);
}

template<typename T>
void LoggerImpl::_logger(loglevel level, const T& message, const std::string& logFile)
{
        std::string levelStr;
        if(level == loglevel::trace)
                levelStr = "TRACE";
        if(level == loglevel::debug)
                levelStr = "DEBUG";
        if(level == loglevel::error)
                levelStr = "ERROR";
        {
                std::lock_guard<std::mutex> lock(_loggingMutex);
                std::cout << "[" <<_getCurrentTimestamp() << ":" << levelStr << "] "<< message << std::endl;
        }
}

template<typename T>
void LoggerImpl::trace(const T&  message, const std::string& logFile)
{
        _logger(loglevel::trace, message, logFile);
}

template<typename T>
void LoggerImpl::debug(const T&  message, const std::string& logFile)
{
        _logger(loglevel::debug, message, logFile);
}

Logger.cpp

#include "LoggerImpl.h"
#include <string>

class Logger
{
        std::string logFile;
        LoggerImpl* log;
        loglevel level;
        public:
        Logger(const std::string& logFile, loglevel level)
        {
                this->logFile = logFile;
                this->level = level;
                log = LoggerImpl::getInstance();
        }
        template<typename T>
        void operator()(const T& message)
        {
                if(level== loglevel::trace)
                        log->trace(message, logFile);
                if(level== loglevel::debug)
                        log->debug(message, logFile);
                if(level== loglevel::error)
                        log->error(message, logFile);
        }
};
int main()
{
        Logger DEBUG_LOG("FileName.log", loglevel::debug);
        DEBUG_LOG("sourav");
}

LoggerImpl.h

#ifndef __LOGGER_H__
#define __LOGGER_H__

#include "LoggerEnums.h"
#include <iostream>
#include <mutex>

class LoggerImpl
{
        static LoggerImpl* _instance;
        static std::mutex _loggerMutex;
        std::mutex _loggingMutex;
        LoggerImpl();

        template<typename T>
        void _logger(loglevel, const T&, const std::string&);

        std::string _getCurrentTimestamp();
        public:
        static LoggerImpl* getInstance();

        template<typename T>
        void trace(const T&  val, const std::string&);

        template<typename T>
        void debug(const T&  val, const std::string&);

        template<typename T>
        void error(const T&  val, const std::string&);
};
#endif

While building I am getting the following error:

/tmp/ccYaFOSe.o: In function `void Logger::operator()<char [7]>(char const (&) [7])':
Logger.cpp:(.text._ZN6LoggerclIA7_cEEvRKT_[_ZN6LoggerclIA7_cEEvRKT_]+0x32): undefined reference to `void LoggerImpl::trace<char [7]>(char const (&) [7], std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
Logger.cpp:(.text._ZN6LoggerclIA7_cEEvRKT_[_ZN6LoggerclIA7_cEEvRKT_]+0x59): undefined reference to `void LoggerImpl::debug<char [7]>(char const (&) [7], std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
Logger.cpp:(.text._ZN6LoggerclIA7_cEEvRKT_[_ZN6LoggerclIA7_cEEvRKT_]+0x80): undefined reference to `void LoggerImpl::error<char [7]>(char const (&) [7], std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status

Can anyone please help, where I am getting wrong.

Aucun commentaire:

Enregistrer un commentaire