Home > OS >  How to specify default initialization conditionally based on templated member variable type
How to specify default initialization conditionally based on templated member variable type

Time:01-05

I have a templated class that uses std::conditional to determine the type of a particular member variable. However, I'd like to also change the default initialisation behaviour (either in the ctor list initialisation, or in the member declaration itself) depending on that condition, as one of the options is a singleton. e.g.

#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;
};

This does not compile when UseSingleton = true as m_member cannot use the default ctor for Singleton. How can I set m_member to initialise from MultipleSubscriberListener::getInstance() if UseSingleton = true?

CodePudding user response:

In c 20 you could define 2 constructors and add the requirements:

MyClass() requires(UseSingleton)
: m_member(Singleton::getInstance())
{}

MyClass() requires(!UseSingleton)
{}

CodePudding user response:

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

If you don't want this to be a default initializer, you can also put it in the member initializer list of the constructor.

Instead of a lambda you can also use a member function if that looks cleaner to you. In either case the return type should be decltype(m_member), so that the reference is passed on instead of decayed.

You could also use decltype(auto), however with that there is potential for undefined behavior. If you use decltype(auto) and don't construct the NotSingleton object directly in the return statement (instead of passing it on from e.g. a local variable), then you would return a dangling reference, causing undefined behavior in the construction of the member.

  •  Tags:  
  • Related