我想有条件地向基类添加一些数据成员,以派生数据成员的存在为条件。
在下面的例子中,
Extra
是基类模板,将在模板参数Enable
上进行切换。
consteval
函数enable
用于检测派生数据成员是否存在,其返回值将用于选择我们想要的Enable
版本。
Foo
是我们要添加额外功能的基类,Bar
是派生类型,它声明我们正在使用的启用额外功能的必需成员。
#include <iostream>
template<bool Enable>
struct Extra
{
static constexpr bool is_enabled = false;
};
template<>
struct Extra<true>
{
static constexpr bool is_enabled = true;
int extra { 42 };
};
template<typename T>
consteval bool enable()
{
if constexpr (requires { T::enable_extra; })
return true;
else
return false;
}
template<typename T>
struct Foo : Extra<enable<T>()>
{
using Base = Extra<enable<T>()>;
using Base::is_enabled;
void eval()
{
if constexpr (is_enabled)
{
if (static_cast<T*>(this)->enable_extra)
std::cout << "extra=" << Base::extra << '\n';
}
}
};
struct Bar : Foo<Bar>
{
const bool enable_extra = true;
};
int main()
{
Bar b;
b.eval();
return 0;
}
可以说它不起作用,并且
enable<T>()
在调用它时评估为 false。
我目前的假设是,这是由于
Bar
在实例化 Foo
时不完整,因此 T::enable_extra
尚不存在,因此 if constexpr
的计算结果为 false。
我在这里尝试做的事情可能吗?我可以根据派生类中成员的存在添加基类功能吗?
我不确定这是否满足您的要求,但如果
extra
的值不需要在类中,这可能会起作用。
#include <iostream>
#include <concepts>
template<typename T>
concept has_enable_extra = requires
{
{ T::enable_extra } -> std::same_as<bool&>;
};
template <has_enable_extra T>
static constexpr int extra = 42;
template <typename T>
struct Foo
{
void eval()
{
if constexpr (has_enable_extra<T>)
{
if (static_cast<T*>(this)->enable_extra)
std::cout << "extra=" << extra<T> << '\n';
}
}
};
struct Bar : Foo<Bar>
{
bool enable_extra = true;
};
static_assert(has_enable_extra<Bar>);
int main()
{
Bar b;
b.eval();
return 0;
}