匹配模板类中的CRTP
Matching CRTP in template class
本文关键字:CRTP 更新时间:2023-10-16
最近我一直在摆弄模板,偶然发现了以下问题。我像这样实现CRTP模式:
template<typename derived_t>
struct protocol_object
{
...
};
struct data_object : public protocol_object<data_object>
{
...
};
我现在想在成员模板函数中匹配class protocol_object
的实例,同时仍然接受非crtp类型:
struct consumer_impl
{
template<typename derived_t>
void match(protocol_object<derived_t> &value)
{
std::cout << "protocol_class";
};
template<typename T>
void match(T &value)
{
std::cout << "any other type";
};
}
不幸的是,只调用了第二个版本。显然,match(protocol_object<derived_t> &value)
没有被考虑或拒绝,而倾向于更一般的形式match(T &value)
。
data_object object;
double value;
consumer_impl consumer;
consumer.match(value); // yields "any other type" OK
consumer.match(object); // also yields "any other type" but want "protocol_class"
有出路吗?
谢谢你的提示。阿恩
这与CRTP无关。这是下列情况的一般情况:
- 设计一个模板函数,使得所有的派生类都使用特定的特化。
问题是T& value
是Derived&
的精确匹配,而Base&
是不精确匹配。因此,我们将使一般形式更差:
struct conversion_required { conversion_required(int) {} };
template<typename derived_t>
void match_impl(protocol_object<derived_t> &value, int)
{
std::cout << "protocol_class";
};
template<typename T>
void match_impl(T &value, conversion_required)
{
std::cout << "any other type";
};
template<typename T>
void match(T& value)
{
return match_impl(value, 0);
}
现在,需要向上转换的专门化比需要用户定义转换的通用模板更匹配。
重载解析是基于静态类型执行的,因为它是编译时编译器的决策。试试这个:
consumer.match(static_cast<protocol_object<data_object>&>(object));
第二个函数是一个更好的匹配,因为它不需要转换,而第一个函数需要从派生到基的转换。
你可以使用boost来克服这个问题:
template <class T>
void
match (typename boost::enable_if_c
<boost::is_base_of<protocol_object<T>,T>::value, T>::type& t)
{
std::cout << "protocol_class";
}
template <class T>
void
match (typename boost::disable_if_c
<boost::is_base_of<protocol_object<T>,T>::value, T>::type& t)
{
std::cout << "any other type";
}
这将适用于所有从protocol_object<T>
派生的T
类,但不适用于protocol_object<T>
本身。您可以为它添加另一个重载(基本上,重用您的第一个match
函数),或者修改enable_if
中的条件,使其也匹配protocol_object<T>
。
相关文章:
- 尝试使用继承和模板实现CRTP.Visual Studio正在生成编译器错误
- CRTP 单一实例不完整类型或非文本类型
- CRTP 中的复制赋值运算符 - gcc vs clang 和 msvc
- 将具有固定签名的自定义函数名称注入 CRTP
- 如何在MISRA C++之后实施CRTP
- 检测使用 CRTP 的类中的成员函数
- 简化使用 CRTP 模式的类的声明
- C++ CRTP initialization
- 概念可以与 CRTP 习语一起使用吗?
- CRTP - 危险的内存访问?
- 如何断言 CRTP 的函数为最终函数?
- CRTP 模式不会触发完整的模板实例化
- 在 CRTP 中使用嵌套名称说明符
- CRTP 与基类向量
- 派生的成员 通过指向基、static_cast、crtp、删除模板的指针
- 为什么 CRTP 模板C++给出无效参数错误?
- CRTP相对于抽象类的优势
- 具有unique_ptr的 CRTP 会导致段错误
- CRTP 如何使派生类具有基类的容器
- 使用 CRTP 实现单例