我在MSVC ++ 17版本15.5.5中实现单例模式时遇到问题。我正在使用标志/std:c++17
编译。
我的实现包含以下帮助程序类:
#pragma once
#include <cassert>
template<class T>
class Singleton : private T
{
public:
virtual ~Singleton() = default;
template<typename ... Targs>
static T & initInstance(Targs && ... args)
{
assert(instance == nullptr);
instance = new Singleton<T>(std::forward<Targs>(args)...); //The constructor of T might be inaccessible here so let our own ctor call it
return *instance;
}
static T & getInstance()
{
assert(instance != nullptr);
return *instance;
}
private:
template<typename ... Targs>
explicit Singleton(Targs && ... args)
: T{ std::forward<Targs>(args)... }
{}
static T * instance;
};
template<class T>
T * Singleton<T>::instance = nullptr;
此实现的一个目标是使用某种形式的延迟初始化,但没有每次调用if
时执行的冗余getInstance()
语句。只有第一次才有用,因为实例需要初始化,但之后if
只是开销。为此,我创建了在调用initInstance()
之前必须调用的函数getInstance()
。我很清楚assert()
只能在调试模式下工作,但这对我的项目来说很好。
该课程旨在以下列方式使用:
#include "Singleton.h"
#include <iostream>
class Foo
{
public:
virtual ~Foo() = default;
protected: //has no public ctor's
Foo(int i) //has no default ctor
: i{ i }
{
std::cout << "foo ctr " << i << "\n"; //Not printed if no ctor of Foo is found
}
private:
int i;
};
int main(int argc, char** argv)
{
Singleton<Foo>::initInstance(5); //Selects and executes Foo(int i).
//Singleton<Foo>::initInstance(); //Should not compile, yet it does. Calls no ctor of Foo at all.
Foo & theOnlyFoo = Singleton<Foo>::getInstance(); //or just use the return value of initInstance(5) to initialize this reference
//...
return 0;
}
问题:
如果我在没有任何参数的情况下调用Singleton<Foo>::initInstance();
,即使Foo
没有默认构造函数,代码仍会编译并运行。我原本期望实例化Singleton<Foo>
的构造函数会失败,因为它使用给定的参数调用Foo
的构造函数但是在查找时它不应该能够找到合适的构造函数。然而代码以某种方式编译。
当我执行代码时,Singleton<Foo>
的构造函数被调用,但Foo
的构造函数本身并不是。当我在instance
初始化之后在断点处停止执行并检查其数据库i
的值时,它是一个随机的巨大负值,表明没有执行任何代码来初始化{{1}的实例1}}。
只有在没有Foo
的适当构造函数调用时才会发生这种情况。如果有,一切正常,并且Foo
选择的构造函数被调用。
答案 0 :(得分:0)
正如评论中所建议的,这可能是编译器错误。我提交了一份错误报告。
我还提交了我在评论中描述的内部编译器错误的错误报告。当我(错误地)将using T::T;
放入Singleton<T>::InitInstance()
然后调用T
的构造函数时,会发生内部编译器错误。