与模板类的隐式转换
Implicit conversions with template classes
本文关键字:转换 更新时间:2023-10-16
我试图定义一个类模板,可以做一些输入/输出操作(通过操作符<<和>>从另一个类)在许多数据结构上。
总之,我可以做例如:
vector<int> x;
map<string,vector<vector<int>>> y;
const int z = 42;
FooStream fs;
Foo<decltype(x)> fx(x);
Foo<decltype(y)> fy(y);
Foo<decltype(z)> fz(z);
fs << fx << fy << fz >> fy >> fx;
我的问题是我怎样才能到达这个:
vector<int> x;
map<string,vector<vector<int>>> y;
const int z = 42;
FooStream fs;
fs << x << y << z >> y >> x;
//error : no operator found which takes a right-hand operand of type 'std::vector<_Ty>' (or there is no acceptable conversion)
FooStream: operator<& lt;和>>应该接受任何类型T,当专门化Foo<</p>
更多细节,这里是我的(简化)代码。
class FooBase1{
protected:
union p_type{const void *p1;void *p2;} p;
public:
FooBase1(const void *v){p.p1 = v;};
virtual void func1_() = 0;
};
class FooBase2 : public FooBase1{
public:
FooBase2(void *v) : FooBase1(v){};
virtual void func2_() = 0;
};
template<typename T,typename Enable=void>
class Foo{
public:
typedef void generic;
};
template<typename T,typename E=void> struct is_generic : std::false_type{};
template<typename T> struct is_generic<T,typename Foo<T>::generic> : std::true_type {};
template<typename T,typename T2=void> struct enable_if_ng : enable_if<!is_generic<T>::value,T2> {};
template<typename T> struct get_foo_type {};
template<typename T> struct get_foo_type<Foo<T> > {typedef T type;};
#define DECLARE_FOO_SPECIALIZATION(Type)
template<>
class Foo<Type> : public FooBase2{
public:
Foo(Type &v) : FooBase2(&v){}
virtual void func1_(){func1(*(const Type *)p.p2);}
virtual void func2_(){func2(*(Type *)p.p2);}
static void func1(const Type&){/*user defined*/}
static void func2(Type&){/*user defined*/}
};
//friend FooStream& operator>>(FooStream& fs,Type &f){Foo<Type>(f).func2_();return fs;} doesn't work
DECLARE_FOO_SPECIALIZATION(bool)
DECLARE_FOO_SPECIALIZATION(int)
DECLARE_FOO_SPECIALIZATION(long)
DECLARE_FOO_SPECIALIZATION(float)
DECLARE_FOO_SPECIALIZATION(double)
DECLARE_FOO_SPECIALIZATION(string)
template<typename T1>
class Foo<vector<T1>,typename enable_if_ng<T1>::type> : public FooBase2{
public:
Foo(vector<T1> &v) : FooBase2(&v){}
virtual void func1_(){func1(*(const vector<T1> *)p.p2);}
virtual void func2_(){func2(*(vector<T1> *)p.p2);}
static void func1(const vector<T1>&){/*user defined*/}
static void func2(vector<T1>&){/*user defined*/}
};
template<typename T1,typename T2>
class Foo<map<T1,T2>,typename enable_if<!is_generic<T1>::value && !is_generic<T2>::value>::type> : public FooBase2{
public:
Foo(map<T1,T2> &v) : FooBase2(&v){}
virtual void func1_(){func1(*(const map<T1,T2> *)p.p2);}
virtual void func2_(){func2(*(map<T1,T2> *)p.p2);}
static void func1(const map<T1,T2>&){/*user defined*/}
static void func2(map<T1,T2>&){/*user defined*/}
};
template<typename T1>
class Foo<const T1,typename enable_if_ng<T1>::type> : public FooBase1{
public:
Foo(const T1 &v) : FooBase1(&v){}
virtual void func1_(){func1(*(const T1 *)p.p1);}
static void func1(const T1& v){Foo<T1>::func1(v);}
};
class FooStream{
public:
FooStream(){};
FooStream& operator<<(FooBase1 &f){f.func1_();return *this;};
FooStream& operator>>(FooBase2 &f){f.func2_();return *this;};
};
(附加问题:我可以用模板替换宏DECLARE_FOO_SPECIALIZATION吗?我应该改变我的类层次吗?)
谢谢。
这个EnableIf
在许多编译器中不起作用,但是您可以在那里使用更粗糙的SFINAE技巧:
template<std::size_t n>
struct secret_enum { enum class type {}; };
template<bool b, std::size_t n = 0>
using EnableIf = typename std::enable_if< b, typename secret_enum<n>::type >::type;
template<typename T, bool b=true>
struct can_be_fooed : std::false_type {};
template<typename T>
struct can_be_fooed<T, std::is_same<Foo<T>, Foo<T>>::value>:std::true_type {};
class FooStream{
public:
template<typename T, EnableIf<can_be_fooed<typename std::decay<T>::type>>...>
FooStream& operator<<(T&&t){
// body of <<, possibly involving wrapping the t in a Foo<T>?
};
};
当测试这类代码时,当第一行会失败时,停止在一行上做15件事。一次测试一个步骤。使用模板元编程,您正在调试编译步骤——通过以字节大小的块进行编译并在每个步骤进行检查,您正在做的相当于逐步执行代码。
代替宏,创建一个trait类,其中所讨论的元素是唯一具有true
的元素。然后只需使用SFINAE编写一个仅为这些类型打开的template
。相同的代码行数,但没有由宏生成的代码。
template<typename T> struct do_stuff : std::false_type {};
template<> struct do_stuff<int> : std::true_type {};
template<> struct do_stuff<bool> : std::true_type {};
// yada yada
template<typename T>
class Foo<T, typename=typename std::enable_if< do_stuff<T>::value >::type> : public FooBase2 {
public:
Foo(T &v) : FooBase2(&v){}
virtual void func1_(){func1(*(const T *)p.p2);}
virtual void func2_(){func2(*(T *)p.p2);}
static void func1(const T&){/*user defined*/}
static void func2(T&){/*user defined*/}
};
相关文章:
- 防止主数据类型C++的隐式转换
- 模板参数替换失败,并且未完成隐式转换
- 努力将整数转换为链表。不知道我在这里做错了什么
- HEX值到wchar_t字符(UTF-8)的转换
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将 Qvector<uint8_t> 转换为 QString
- 如何在cuSparse中使用cusparseXcoo2csr从coo转换为csc
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- 在c++中使用nlohmann从类到json的转换
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 处理小于cpu数据总线的数据类型.(c++转换为机器代码)
- 如何使用OpenCV将RBG图像转换为HSV,并将H、S和V值保存为C++中的3个独立图像
- 复制列表初始化的隐式转换的等级是多少
- 正在将指针转换为范围
- 如何防止 c++ 在从浮点型转换为双精度型(不适用于 IO)时添加额外的小数?
- 将"打开的CV图像"中的"颜色"转换为整数格式
- 是否可以从int转换为enum类类型
- 了解 GLM- openGL 中的相机转换
- 将无符号char*转换为std::istream*C++