我可以重用同一个模板来声明/定义多个东西吗(而不复制模板代码)
Can I reuse the same template to declare/define multiple things (without duplicating the template code)?
我目前正在编写一个类,它有一些奇特的模板来定义它的一些成员,但其中一些模板完全相同。考虑以下代码(这些都是类成员):
template <typename T, typename = enable_if_t<is_convertible<int, T>::value>>
T get() const { return convert_self_to_int(); }
template <typename T, typename = enable_if_t<is_constructible<T, string>::value>, typename = void>
T get() const { return convert_self_to_string(); }
template <typename T, typename = enable_if_t<is_convertible<int, T>::value>>
operator T() const { return get<T>(); }
template <typename T, typename = enable_if_t<is_constructible<T, string>::value>, typename = void>
operator T() const { return get<T>(); }
正如您所看到的,我有一个名为get
的模板化成员函数,它使用长且有些难以阅读的模板代码。
这一部分对这个问题并不重要,但这里对所有这些花哨的模板进行了简要解释:
get
是一个函数可以以以下两种格式之一返回数据:如果模板参数T
为int
可以转换成的类型,然后是积分返回数据的表示形式(从而触发转换到所请求的类型,我们知道这是可能的)。如果T
是什么可以由string
构造,然后由string
构造返回数据的表示形式(再次触发从CCD_ 9构造CCD_ 8)。任何其他类型落入这些类别将简单地导致编译时错误,这正是这个代码想要做的
这个类还定义了简单的转换运算符,这些运算符是根据get
编写的。
既然这些操作符使用了与get
的相应定义完全相同的模板,我能以某种方式避免复制所有讨厌的模板代码吗?我可以重用一行模板代码来定义多个内容,使代码更可读吗?
您可以使用SFINAE将operator T()
转发到get<T>
。这样,您只需要一个operator T()
:
template <class T, class = decltype(std::declval<ClassName>().get<T>())>
operator T() const {
return get<T>();
}
此外,对于多个SFINAE,您可以更改enable_if_t
以获得默认的int
:,而不是不断添加额外的typename=void
template <class T, std::enable_if_t<std::is_convertible<int, T>::value, int> = 0>
T get() const { return convert_self_to_int(); }
template <class T, std::enable_if_t<std::is_convertible<std::string, T>::value, int> = 0>
T get() const { return convert_self_to_string(); }
不幸的是,这在clang中不起作用,所以我只建议翻转订单。将operator T()
设为SFINAE-d:
template <class T, std::enable_if_t<std::is_convertible<int, T>::value, int> = 0>
operator T() const { return convert_self_to_int(); }
template <class T, std::enable_if_t<std::is_convertible<std::string, T>::value, int> = 0>
operator T() const { return convert_self_to_string(); }
只要让get
前进:
template <class T> T get() const { return operator T(); }
这里的优点是我们不复制任何东西,std::is_convertible<>
类型的特性将正确工作——因为operator T()
是SFINAE-d。get<T>()
上的测试会失败,但这似乎不是通常可以测试的。
- 以下示例中如何避免代码复制?C++/库达
- 如何使用从C++代码写入时复制 BTRFS?
- 如果 iostream 对象不可复制,为什么以下代码是合法的?
- 为什么我的代码在尝试复制字符数组时引发 C6386 错误?
- 是否可以避免在以下代码中复制/移动构造函数的需要?
- 为什么在我的代码中调用复制构造函数而不是移动构造函数?
- 为什么在使用转换构造函数编译代码时需要 const 复制构造函数?
- C++具有移动和复制构造函数的类中的代码重复
- 如何在不复制此代码的情况下将多个函数放入多个命名空间?
- 表示行为与复制代码块的函数参数?
- 避免使用 auto 关键字从字面上复制 const 和非 const 的代码?
- 为什么在下面的代码中调用复制构造函数两次
- 是否可以动态翻译QT应用程序而无需复制代码
- 模板类是否C++使用的每种指针类型复制代码
- 程序无法编译,即使我正在从书中复制代码
- 重载C++模板函数而不复制代码
- 如何在不复制代码的情况下克隆子类
- 在不复制代码的情况下,从工厂实例化一个对象(如炮塔)的草稿(即原型)
- 使用流模板以避免复制代码会产生"错误 C4430:缺少类型说明符 - 假定为 int"
- 树数据结构的深度复制在c++中没有样板复制代码