I create a singleton class to wrap some ofstream
struct OutputFiles {
public:
std::ofstream minus_total, plus_total, HoughMappingMinus_cc, HoughMappingPlus_cc;
template <typename T>
static void init(OutputFilesName<T>& files_name) {
instance_impl(files_name);
}
static OutputFiles& instance() {
return instance_impl();
}
template <typename T>
OutputFiles(OutputFilesName<T>& files_name) :
minus_total(files_name.resut_subdir_name + "/" + files_name.result_file_name_data_M),
plus_total(files_name.resut_subdir_name + "/" + files_name.result_file_name_data_P),
HoughMappingMinus_cc(files_name.resut_subdir_name + "/" + files_name.result_file_name_M_CC),
HoughMappingPlus_cc(files_name.resut_subdir_name + "/" + files_name.result_file_name_P_CC)
{ }
OutputFiles() = default;
OutputFiles(const OutputFiles&) = delete;
OutputFiles& operator=(const OutputFiles&) = delete;
private:
template <typename... Args>
static OutputFiles& instance_impl(Args&&... args) {
static OutputFiles singleton( std::forward<Args&&>(args)... );
return singleton;
}
};
This class must be initialize with OutputFilesName<T>
class
template <typename T>
struct OutputFilesName {
OutputFilesName(
const T&& i_resut_subdir_name,
const T&& i_result_file_name_M_CC,
const T&& i_result_file_name_P_CC,
const T&& i_result_file_name_data_M,
const T&& i_result_file_name_data_P
) :
resut_subdir_name(i_result_file_name_M_CC),
result_file_name_M_CC(i_result_file_name_M_CC),
result_file_name_P_CC(i_result_file_name_P_CC),
result_file_name_data_M(i_result_file_name_data_M),
result_file_name_data_P(i_result_file_name_data_P)
{ }
const T resut_subdir_name;
const T result_file_name_M_CC;
const T result_file_name_P_CC;
const T result_file_name_data_M;
const T result_file_name_data_P;
};
I write main code invoke it:
int main(){
OutputFilesName<std::string> fn{"fa_name","fb_name","aa","bb","cc"};
fs::create_directory(fn.resut_subdir_name);
OutputFiles::init(fn);
OutputFiles::instance().minus_total << "1" << std::endl;
OutputFiles::instance().plus_total << "2" << std::endl;
OutputFiles::instance().HoughMappingMinus_cc << "3"<< std::endl;
OutputFiles::instance().HoughMappingPlus_cc << "4"<< std::endl;
bool open1 = OutputFiles::instance().minus_total.is_open();
bool open2 = OutputFiles::instance().plus_total.is_open();
bool open3 = OutputFiles::instance().HoughMappingMinus_cc.is_open();
bool open4 = OutputFiles::instance().HoughMappingPlus_cc.is_open();
std::cout << open1 << open2 << open3 << open4 << std::endl;
}
The result and full code here,
ofstream
seems can't be open.
Files and directory has been created,
but the content is empty.
I'm confused.
This is a strange way to manage objects.
Your OutputFiles::init(fn)
invokes instance_impl(fn)
, a function template specialisation. That specialisation has a static
local variable called singleton
, instantiated with ctor args fn
, to which you return a reference. All good.
Then, you do OutputFiles::instance()
to get a OutputFiles&
. Trouble is, that function invokes instance_impl()
, a different function template specialisation. That specialisation also has a static
local variable called singleton
, default-constructed. All of its ofstream
members have also thus been default-constructed, and streaming to them accomplishes nothing.
The key is that the two specialisations of instance_impl
are different functions. So this is not a valid way to bypass static initialisation.
Why not just instantiate an OutputFiles
in the normal way and store it somewhere?