如何根据模板化成员变量类型有条件地指定默认初始化
How to specify default initialization conditionally based on templated member variable type
我有一个模板化的 class,它使用 std::conditional
来确定特定成员变量的类型。但是,我还想根据该条件更改默认初始化行为(在 ctor 列表初始化中,或在成员声明本身中),因为其中一个选项是单例。
例如
#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 的默认构造函数。如果 UseSingleton = true
?
如何设置 m_member 从 MultipleSubscriberListener::getInstance()
初始化
std::conditional_t<UseSingleton, Singleton&, NotSingleton> m_member =
[]() -> decltype(m_member) {
if constexpr (UseSingleton)
return Singleton::getInstance();
else
return {};
}();
如果你不希望它成为默认初始化器,你也可以将它放在构造函数的成员初始化器列表中。
除了 lambda,您还可以使用成员函数,如果它看起来更清晰的话。在任何一种情况下,return 类型都应为 decltype(m_member)
,以便传递引用而不是衰减。
您也可以使用 decltype(auto)
,但是这样做可能会出现未定义的行为。如果您使用 decltype(auto)
并且不直接在 return statement
中构造 NotSingleton
对象(而不是从例如局部变量传递它),那么您将 return a悬挂引用,导致成员构造中的未定义行为。
在 c++20 中,您可以定义 2 个构造函数并添加要求:
MyClass() requires(UseSingleton)
: m_member(Singleton::getInstance())
{}
MyClass() requires(!UseSingleton)
{}
我有一个模板化的 class,它使用 std::conditional
来确定特定成员变量的类型。但是,我还想根据该条件更改默认初始化行为(在 ctor 列表初始化中,或在成员声明本身中),因为其中一个选项是单例。
例如
#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 的默认构造函数。如果 UseSingleton = true
?
MultipleSubscriberListener::getInstance()
初始化
std::conditional_t<UseSingleton, Singleton&, NotSingleton> m_member =
[]() -> decltype(m_member) {
if constexpr (UseSingleton)
return Singleton::getInstance();
else
return {};
}();
如果你不希望它成为默认初始化器,你也可以将它放在构造函数的成员初始化器列表中。
除了 lambda,您还可以使用成员函数,如果它看起来更清晰的话。在任何一种情况下,return 类型都应为 decltype(m_member)
,以便传递引用而不是衰减。
您也可以使用 decltype(auto)
,但是这样做可能会出现未定义的行为。如果您使用 decltype(auto)
并且不直接在 return statement
中构造 NotSingleton
对象(而不是从例如局部变量传递它),那么您将 return a悬挂引用,导致成员构造中的未定义行为。
在 c++20 中,您可以定义 2 个构造函数并添加要求:
MyClass() requires(UseSingleton)
: m_member(Singleton::getInstance())
{}
MyClass() requires(!UseSingleton)
{}