我有一个模板化基类,它定义了某种默认 功能,如果需要,模板化派生类可以重载这些功能。此“默认”功能作为采用任何参数的可变参数模板函数实现。
如果用户未能正确定义派生类的原型(prototype),则将无意中调用基类方法。
相反,如果派生类的编写者希望为现有函数实现新的原型(prototype),那么基类对于该函数名称将变得过时(它不会为其他选择不选择的派生方法提供通用的“回退”定义钩子(Hook)的这个特定原型(prototype))。
所以...我不想长篇大论,而是举例说明我正在尝试做的事情:
template <typename Derived>
class Base
{
template <typename... Args>
void hook1(const Args&...) // -> std::enable_if(Derived::hook1 doesn't exist)
{
// do nothing
}
template <typename... Args>
void hook2(const Args&...) // -> std::enable_if(Derived::hook2 doesn't exist)
{
// do nothing
}
// ... hook3, hook4, etc.
};
// this particular derived class overloads only hook1
class DerivedExample : public Base<DerivedExample>
{
template <typename SomeArg>
void hook1(const SomeArg& arg)
{
// do something
}
};
显然,那些 enable_if
语句没有任何意义,但它们说明了我希望拥有的功能。这可以实现吗?
最佳答案
首先,您必须定义一些特征。特别是像这样测试成员函数是否存在的函数:
struct has_hook_one_impl {
template<typename T>
static auto test(int) -> decltype(std::declval<T&>().hook1(0), std::true_type{});
template<typename...>
static std::false_type test(...);
};
template<typename T>
struct has_hook_one : public decltype(has_hook_one_impl::test<T>(0)) {};
此特征使用表达式 SFINAE 来检测成员的存在,您可以阅读有关表达式 SFINAE 的更多信息 here .
定义此特征后,其用法变得简单,您可以定义其他类似的特征。所以在你的情况下,enable_if
会是这样的:
template <typename Derived>
class Base
{
template <typename... Args>
auto hook1(const Args&...) -> typename std::enable_if<!has_hook_one<Derived>::value>::type
{
// do nothing
}
};
实现检测其他成员函数存在的其他元函数应该很容易扩展,并且作为练习留给了读者。
关于c++ - 如何让基方法只在派生类没有定义同名方法的情况下定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25070101/