如何根据模板化的成员变量类型有条件地指定默认初始化



我有一个模板化的类,它使用std::conditional来确定特定成员变量的类型。然而,我也想根据该条件更改默认的初始化行为(在ctor列表初始化中,或在成员声明本身中(,因为其中一个选项是singleton。例如

#include <type_traits>
class NotSingleton{
public:
NotSingleton() = default;
};
class Singleton{
public:
static Singleton& getInstance(){
static Singleton singleton;
return singleton;
}
// delete copy ctor/assignment etc.
private:
Singleton() = default;
~Singleton() = default;
};
template<bool UseSingleton>
class MyClass{
public:
MyClass() {}
private:
std::conditional_t<UseSingleton, Singleton&, NotSingleton> m_member;
};

UseSingleton = true作为m_member不能使用Singleton的默认ctor时,这不会编译。如果UseSingleton = true,我如何设置m_member从MultipleSubscriberListener::getInstance()初始化?

在c++20中,您可以定义2个构造函数并添加需求:

MyClass() requires(UseSingleton)
: m_member(Singleton::getInstance())
{}
MyClass() requires(!UseSingleton)
{}
std::conditional_t<UseSingleton, Singleton&, NotSingleton> m_member =
[]() -> decltype(m_member) {
if constexpr (UseSingleton)
return Singleton::getInstance();
else
return {};
}();

如果不希望它是默认的初始值设定项,也可以将它放在构造函数的成员初始值设定值列表中。

如果您觉得成员函数更简洁,您也可以使用它来代替lambda。在任何一种情况下,返回类型都应该是decltype(m_member),这样引用就会被传递而不是衰减。

您也可以使用decltype(auto),但是有了它,就有可能出现未定义的行为。如果您使用decltype(auto),并且不直接在return statement中构造NotSingleton对象(而不是从例如局部变量传递(,那么您将返回一个悬空引用,从而在成员的构造中导致未定义的行为。

最新更新