避免在C ++中的实例上调用多个函数成员

时间:2015-08-17 15:52:56

标签: c++ logging static-assert

我为我的程序编写了一个logger类,但我想强制客户端以特定的方式使用我的类。这是我的Logger课程:

#ifndef __LOGGER_HPP
#define __LOGGER_HPP

#include <Uncopyable.hpp>
#include <sstream>

enum LoggerLevel
{
    ERROR,
    WARNING,
    INFO,
    DEBUG,
    ALL
};

class Logger : private Uncopyable
{
    private:

        static LoggerLevel reportingLevel;
        static std::ostringstream os;
        static bool hide;
        static std::string file;

        LoggerLevel messageLevel;
        std::string className;

    public:

        static void setVerbosity(LoggerLevel level);
        static void setLogFile(const std::string &file);
        static void hideOutput();
        static bool outputHidden();
        static std::ostringstream &getStream();

        Logger(const std::string &className);
        ~Logger();
        std::ostringstream &debug();
        std::ostringstream &info();
        std::ostringstream &warning();
        std::ostringstream &error();
};

#endif // __LOGGER_HPP

实施:

#include <Logger.hpp>
#include <iostream>
#include <fstream>
#include <cstdio>
#include <ctime>

using namespace std;

LoggerLevel Logger::reportingLevel = LoggerLevel::ALL;
ostringstream Logger::os;
string Logger::file;
bool Logger::hide = false;

Logger::Logger(const string &className) :
    className(className)
{
    os.str("");
}

Logger::~Logger()
{
    os << endl;

    if (this->messageLevel <= reportingLevel)
    {
        if (!hide)
        {
            if (this->messageLevel == LoggerLevel::ERROR)
            {
                cerr << os.str() << flush;
            }
            else
            {
                cout << os.str() << flush;
            }
        }

        if (!file.empty())
        {
            time_t now = time(nullptr);
            string time(ctime(&now));
            ofstream log(file, ios::in | ios::app);
            log << time.substr(0, time.length() - 1) << " " << os.str() << flush;
            log.close();
        }
    }
}

void Logger::setVerbosity(LoggerLevel level)
{
    Logger::reportingLevel = level;
}

void Logger::setLogFile(const string &file)
{
    Logger::file = file;
}

void Logger::hideOutput()
{
    Logger::hide = true;
}

bool Logger::outputHidden()
{
    return hide;
}

ostringstream &Logger::getStream()
{
    return os;
}

ostringstream &Logger::debug()
{
    os << "[DEBUG] " << this->className << ": ";
    this->messageLevel = LoggerLevel::DEBUG;
    return os;
}

ostringstream &Logger::info()
{
    os << "[INFO] " << this->className << ": ";
    this->messageLevel = LoggerLevel::INFO;
    return os;
}

ostringstream &Logger::warning()
{
    os << "[WARNING] " << this->className << ": ";
    this->messageLevel = LoggerLevel::WARNING;
    return os;
}

ostringstream &Logger::error()
{
    os << "[ERROR] " << this->className << ": ";
    this->messageLevel = LoggerLevel::ERROR;
    return os;
}

正如您所看到的,我想强制客户端使用这样的类:

Logger("MyCLass").debug() << "This is a debug message.";

所以我想静态地避免这种用法:

Logger myLogger("MyClass");
myLogger.debug() << "This is a debug message.";
myLogger.info() << "This is an information.";

有没有解决办法? 感谢。

1 个答案:

答案 0 :(得分:3)

是的,有一个解决方案,感谢C ++ 11。您希望rvalue-reference-qualify每个日志记录功能:

std::ostringstream &debug() &&;
// etc.

换句话说,函数声明末尾的&&表示debug()和朋友只能在临时Logger个对象上调用:

Logger("MyClass").debug() << "foo"; // fine

Logger log("MyClass");
log.debug() << "bar"; // compile-time error!