在 class 中声明具有类型特征的友元函数时出现问题
Problem on declaring friend function with type traits in a class
我正在研究 C++ 中的单例模式,想实现一个全局函数来完成 class 的构造。我在该函数中使用了 std::is_base_of
,但这使我无法在 class.
中声明该函数
这是一个简短的例子:
#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
};
以上代码在实例化第一个函数时使用 gcc 或 C2139 使用 MSVC 将导致“不完整类型的无效使用”。
那么,除了让构造函数 B::B()
成为 public 之外,我还有什么办法可以解决这个问题吗?
看来只能用静态成员函数(如B::Instance()
)来实现单例模式,用构造函数来完成具体的功能...
代码:
#include <type_traits>
class A {
protected:
A() {
// Do something special here
}
};
class B : public A {
protected:
B();
public:
static B* Instance() {
static B* b = new B();
return b;
}
};
问题是在定义 class 期间,class 仍然 不完整 、
和 std::is_base_of
需要 Derived
的完整类型,否则你有 UB。
如果您可以访问 C++17,您可能会:
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>();
};
您可以使用模板仿函数构建目标 class 的对象。此仿函数必须是目标 class 的友元。请参阅下面的示例。
#include <type_traits>
#include <tuple>
class A {};
template <typename T>
struct Instance_t
{
T* operator () () const
{
if constexpr (std::is_base_of_v<A, T>)
{
return new T();
}
else
{
return nullptr;
}
}
};
template <typename T>
constexpr Instance_t<T> Instance{};
class B : public A {
protected:
B()
{}
template <typename T> friend struct Instance_t;
};
int main()
{
auto b=Instance<B>();
std::ignore=b;
return 0;
}
检查Demo。
我正在研究 C++ 中的单例模式,想实现一个全局函数来完成 class 的构造。我在该函数中使用了 std::is_base_of
,但这使我无法在 class.
这是一个简短的例子:
#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
};
以上代码在实例化第一个函数时使用 gcc 或 C2139 使用 MSVC 将导致“不完整类型的无效使用”。
那么,除了让构造函数 B::B()
成为 public 之外,我还有什么办法可以解决这个问题吗?
看来只能用静态成员函数(如B::Instance()
)来实现单例模式,用构造函数来完成具体的功能...
代码:
#include <type_traits>
class A {
protected:
A() {
// Do something special here
}
};
class B : public A {
protected:
B();
public:
static B* Instance() {
static B* b = new B();
return b;
}
};
问题是在定义 class 期间,class 仍然 不完整 、
和 std::is_base_of
需要 Derived
的完整类型,否则你有 UB。
如果您可以访问 C++17,您可能会:
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>();
};
您可以使用模板仿函数构建目标 class 的对象。此仿函数必须是目标 class 的友元。请参阅下面的示例。
#include <type_traits>
#include <tuple>
class A {};
template <typename T>
struct Instance_t
{
T* operator () () const
{
if constexpr (std::is_base_of_v<A, T>)
{
return new T();
}
else
{
return nullptr;
}
}
};
template <typename T>
constexpr Instance_t<T> Instance{};
class B : public A {
protected:
B()
{}
template <typename T> friend struct Instance_t;
};
int main()
{
auto b=Instance<B>();
std::ignore=b;
return 0;
}
检查Demo。