В зависимости от того, как я создаю свой объект Log
, я получаю сообщение об ошибке компилятора, в котором говорится, что я пытаюсь сослаться на удаленную функцию (конструктор копирования):
C: \ Projects \ Logger \ src \ Logger. cpp (34,1): ошибка C2280: 'Logger :: Log :: Log (const Logger :: Log &)': попытка ссылки на удаленную функцию [C: \ Projects \ Logger \ build \ Logger.vcxproj]
Ожидается, что мой объект журнала неявно удалил конструктор копирования, потому что:
T имеет non-stati c элементы данных, которые не могут быть скопированы (имеют удаленные, недоступные или неоднозначные конструкторы копирования);
Это имеет смысл из-за std::ofstream
, у которого удален конструктор копирования .
Я не могу понять, почему вообще вызывается конструктор копирования. Как насчет построения с оператором присваивания, который вызывает конструктор копирования? Я компилирую с помощью MSV C, есть ли какой-нибудь флаг компилятора, который я не использую, который не оптимизирует определенное поведение? Например, создать временный объект, затем скопировать конструкцию в именованный объект foo
?
Существует только одно определение конструктора, как показано в блоке кода ниже.
#include <iostream>
#include <string>
#include <fstream>
#include "Logger.h"
#include "LoggerConfig.h"
Logger::Log::Log(std::string file) : filename{ file }
{
logFile = std::ofstream(filename, std::ios::out);
if (logFile.is_open())
{
logFile << "This is a log.\n";
}
else
{
std::cout << "Unable to open filename: " << filename << '\n';
}
}
Logger::Log::~Log()
{
// Wait and take write mutex
// Close file
}
int main()
{
// report version
std::cout << " Version " << LOGGER_VERSION_MAJOR << "."
<< LOGGER_VERSION_MINOR << std::endl;
Logger::Log foo = Logger::Log::Log("sample.log"); // C2280: attemping to reference a deleted function
//Logger::Log foo("sample.log"); // Works!
//Logger::Log foo{"sample.log"}; // Works!
foo.Write(Logger::Log::Level::INFO, "Testing", 123, "hahaha");
return 0;
}
Интерфейс класса logger.h ниже:
#pragma once
namespace Logger
{
class Log
{
private:
std::string filename;
std::ofstream logFile;
public:
enum class Level
{
DEBUG,
INFO,
WARNING,
ERROR
};
Log(std::string file);
~Log();
template<typename T>
void Write(Level lvl, T arg)
{
logFile << arg;
return;
}
template<typename T, typename... Args>
void Write(Level lvl, T firstArg, Args... args)
{
logFile << firstArg;
Write(lvl, args...);
return;
}
};
}