C++ CRTP与SFINAE的混合
我有一个C++ CRTP与SFINAE的混合,c++,metaprogramming,sfinae,crtp,C++,Metaprogramming,Sfinae,Crtp,我有一个base将派生类型作为模板参数。以下代码按预期工作。base的实例化使用non\u default\u impl::data\u t和base引发编译错误,因为event\u data只是一个转发声明 template <typename T> struct event_data; template<typename T> struct tovoid { typedef void type; }; template <typename T, ty
base
将派生类型作为模板参数。以下代码按预期工作。base
的实例化使用non\u default\u impl::data\u t
和base
引发编译错误,因为event\u data
只是一个转发声明
template <typename T>
struct event_data;
template<typename T>
struct tovoid {
typedef void type;
};
template <typename T, typename enable = void>
struct get_data{
typedef event_data<T> type;
};
template <typename T>
struct get_data<T, typename tovoid<typename T::data_t>::type >{
typedef typename T::data_t type;
};
template <typename T>
struct base{
typedef typename get_data<T>::type data_type;
base(){
data_type();
}
};
struct non_default_impl{
struct data{};
typedef data data_t;
};
struct default_impl{
};
int main(){
base<non_default_impl> e1;
base<default_impl> e2;
return 0;
}
struct non_default_impl: public base<non_default_impl>{
struct data{};
typedef data data_t;
};
int main(){
non_default_impl e1;
// base<default_impl> e2;
return 0;
}
prog.cpp:正在实例化'base::base()[with T=
非默认值“\u impl]”:
程序cpp:28:8:从这里开始需要
程序cpp:24:3:错误:不完整类型的使用无效
'base::data_type{aka struct
事件_data}'数据_类型()
如何做到这一点。如果派生类有data\u t
typedef,则使用event\u data
这是CRTP的一个警告:当您的
基本
模板专门用于您的非默认执行
类时,即在其基类列表中,非默认执行
本身尚未定义
因此,任何访问属于其定义一部分的内容(例如data\u t
typedef)的尝试都会失败
由于不能使用非默认\u impl
中的任何内容,因此解决方案是使用外部类型特征来选择数据:
template <class T>
struct dataType { typedef event_data<T> type; };
template <typename T>
struct base{
typedef typename dataType<T>::type data_type;
// ...
};
// Usage
struct non_default_data {};
template <>
struct dataType<struct non_default_impl> {
typedef non_default_data type;
};
struct non_default_impl: public base<non_default_impl> {
// ...
};
模板
结构数据类型{typedef event_data type;};
模板
结构基{
typedef typename dataType::type data_type;
// ...
};
//用法
结构非默认数据{};
模板
结构数据类型{
typedef非默认数据类型;
};
结构非默认值默认值:公共基{
// ...
};
请注意,您不能在非默认\u impl
中声明非默认\u数据,因为它必须可以从type trait访问,而type trait必须可以从CRTP访问,在定义非默认\u impl
之前,还必须对其进行专门化