使用模板模板参数和enable_if正确选择重载
Getting overload selection right with template template params and enable_if
我在VS2013中有一个模板函数,旨在执行任何给定对象的"深层复制"。 一个重载适用于普通类型,只需调用 operator=。 但是我也有一个重载,旨在处理shared_ptr到我自己的 Shape 类对象的向量,这只能通过调用 clone(( 成员函数来复制。
struct Shape { virtual std::shared_ptr<Shape> clone() const = 0; };
struct Rectangle : public Shape { virtual std::shared_ptr<Shape> clone() const override; };
所以我有这个重载,编译器选择它很好
template<class SHP>
inline std::vector<std::shared_ptr<SHP>> deep_copy(
const std::vector<std::shared_ptr<SHP>>& val,
typename std::enable_if<std::is_base_of<Shape, SHP>::value>::type** = nullptr)
{
// ... blah blah blah
}
std::vector<std::shared_ptr<Rectangle>> objects;
auto objects2 = deep_copy(objects);
然后我想更改它以采用shared_ptr的任何非键控集合(例如列表(。 好吧,没问题,我实际上做到了...
template<class COLL>
inline COLL deep_copy(const COLL& val,
typename std::enable_if<std::is_base_of<Shape, typename COLL::value_type::element_type>::value>::type** = nullptr)
但此语法并不能真正确保集合包含shared_ptr。 它只是确保其value_type具有某种形状的嵌套element_type
所以我的问题是,确保集合的内容实际上是 std::shared_ptr 从 Shape 派生的内容的语法是什么?
我已经使用模板模板参数对此进行了多次尝试,但我一直在搞砸它。
让我们从一个测试T
是否为shared_ptr
的概念开始:
template<typename T>
struct is_shared_ptr : std::false_type{};
template<typename T>
struct is_shared_ptr<std::shared_ptr<T>> : std::true_type{};
现在像
std::cout << std::boolalpha << is_shared_ptr<std::shared_ptr<Shape>>::value << std::endl;
将输出
真
接下来,如果某些东西由于使用该概念而产生了true_type
,我们接下来要检查其element type
:
template<typename T>
using element_t = typename std::decay_t<T>::element_type;
查看返回的类型是否派生自 Shape
。
让我们创建另一个帮助程序别名来获取集合中的value_type
:
template<typename T>
using collection_vt = typename std::decay_t<T>::value_type;
现在我们可以将这些概念组合成一个看起来非常粗糙的概念:
template<template<class...> class C, typename U, typename... A>
auto DoTheThing(const C<U, A...>& _collection) -> std::enable_if_t<
is_shared_ptr<collection_vt<decltype(_collection)>>::value &&
std::is_base_of<Shape, element_t<collection_vt<decltype(_collection)>>>::value
>
{
std::cout << _collection.size() << std::endl;
}
初始模板参数用于接受相对通用的容器。然后我们使用尾随返回类型首先确保value_type
是shared_ptr
,然后检查shared_ptr
的element_type
是否派生自Shape
。因为成功后,enable_if
的类型是void
的,函数的返回类型变为无效。
现场演示
这是测试:
std::vector<std::shared_ptr<Shape>> vec1;
DoTheThing(vec1); // success
std::vector<Wrapper<Shape>> vec2;
//DoTheThing(vec2); // error
std::vector<std::shared_ptr<int>> vec3;
//DoTheThing(vec3); // error
std::list<std::shared_ptr<Shape>> vec4;
DoTheThing(vec4); // success
相关文章:
- 如何使用默认参数等选择模板专业化
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 选择要调用的构造函数
- C++选择排序算法中的逻辑错误
- 我的简单if-else语句是如何无法访问的代码
- 如何将enable-if与模板参数和参数包一起使用
- 无论条件是否为true,if总是在c++中执行
- Arduino:for/while/if在void setup()或void loop()之前?——错误:之前需要不合格
- QTreeView幻灯片多选后无法使用单击选择
- 无法获取菜单选择以运行函数.C++
- Qt C++静态thread_local QNetworkAccessManager是线程应用程序的好选择吗
- Insert函数不适用于2 if语句C++
- If语句未被求值C++
- 是否可以在C++中使用三元运算符在 if 语句中选择比较运算符?
- 在 ODEINT 中通过 if 语句选择步进器
- 何时使用 if 语句选择多个循环而不是单个循环
- 有没有修复我的代码没有将 int 声明为我在 if else 循环中选择的内容
- 使用if语句选择类型来声明变量C++
- 如果选择了上面的if语句,那么Will else就是resolve
- 除了这一长串"if argA == argB do ..."之外,还有其他选择吗?