【发布时间】:2020-11-28 12:17:09
【问题描述】:
我制作了一个非常简单的Singleton 基类,它可以与 CRTP 一起使用,以使任何派生自它的类成为单例。不过我发现了一些奇怪的东西。不同的编译器对代码是否格式错误存在分歧。这里是:
template <typename Derived>
class Singleton
{
public:
inline static Derived instance;
};
正如我所说,它非常简单,但这足以用于演示目的。此处显示了一个示例用法:
class MyClass : public Singleton<MyClass>
{
public:
std::string msg;
MyClass() = default;
MyClass(const std::string& msg_) : msg{ msg_ }
{
}
MyClass(std::string&& msg_) noexcept : msg{ std::move(msg_) }
{
}
};
此代码在GCC 和Clang 下编译。然而MSVC 拒绝它,说MyClass 没有提供适当的默认构造函数(尽管它显然被声明为default)。出于好奇,我尝试使用不同的构造函数:
template <typename Derived>
class Singleton
{
public:
inline static Derived instance{"hello MSVC"};
};
class MyClass : public Singleton<MyClass>
{
public:
std::string msg;
MyClass() = default;
MyClass(const std::string& msg_) : msg{ msg_ }
{
}
MyClass(std::string&& msg_) noexcept : msg{ std::move(msg_) }
{
}
};
这再次被GCC 和Clang 接受,但被MSVC 拒绝,这一次声称MyClass 未定义。
问题是:这段代码格式不正确吗?如果是,为什么? 那么,哪些编译器是正确的? GCC 和 Clang 是否只是利用“无需诊断”?
我的直觉是 MSVC 是错误的,因为通常是这种情况,但另一方面,它通常比 GCC 和 Clang 更宽松,所以我很好奇答案。
【问题讨论】:
-
Derived是 CRTP 中的不完整类型。
标签: c++ templates singleton language-lawyer crtp