I'm playing around with the singleton pattern in C++, and want to implement an global function that completes the construction of a class. I used std::is_base_of
in that function, but that makes it impossible for me to declaring the function in the class.
Here's a short example:
#include <type_traits>
class A {};
template<typename T>
typename std::enable_if_t<std::is_base_of_v<A, T>, T*>
Instance() { return T(); }
template<typename T>
typename std::enable_if_t<!std::is_base_of_v<A, T>, T*>
Instance() { return T(); }
class B : public A {
protected:
B();
friend B* Instance<B>(); // Error
};
The above code will cause "invalid use of incomplete type" using gcc or C2139 using MSVC when instantiating the first function.
So, other than making constructor B::B()
to be public, is there any possible way for me to work around with it?
Issue is that during definition of class, the class is still incomplete,
and std::is_base_of
required complete type for Derived
, else you have UB.
If you have access to C++17, you might do:
template<typename T>
T* Instance() {
if constexpr (std::is_base_of_v<A, T>) {
return nullptr; // Your impl
} else {
return nullptr; // Your impl
}
}
class B : public A {
protected:
B();
friend B* Instance<B>();
};