如何让模板函数在适当的时候使用back_inserter而不是机械臂
How to get template function to use back_inserter over inserter when appropriate
如何创建一个函数,将一个集合的内容添加到另一个集合中,如果可能的话,使用std::back_inserter()
提高效率?我没有看到push_back()
的明显特征,我也不是std::enable_if
的专家,但我希望一些组合能够达到以下效果:
// IF HAS_PUSH_BACK:
template<typename CIn, typename COut>
void addAll(CIn && from, COut && to) {
std::copy(std::begin(from), std::end(from), std::back_inserter(to));
}
// IF ! HAS_PUSH_BACK:
template<typename CIn, typename COut>
void addAll(CIn && from, COut && to) {
std::copy(std::begin(from), std::end(from), std::inserter(to, to.begin()));
}
如何创建一个函数,将一个集合的内容添加到另一个集合,如果可能的话,使用back_inserter提高效率?
我想你可以声明一个模板函数,当有push_back()
时返回std::true_type
template <typename T>
constexpr auto hasPushBack (int)
-> decltype( std::declval<T>().push_back(*(std::declval<T>().begin())),
std::true_type() );
以及返回std::false_type
的故障回复功能
template <typename>
constexpr std::false_type hasPushBack (long);
因此,您可以按如下方式修改函数
template<typename CIn, typename COut>
typename std::enable_if<true == decltype(hasPushBack<COut>(0))::value>::type
addAll (CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::back_inserter(to)); }
template<typename CIn, typename COut>
typename std::enable_if<false == decltype(hasPushBack<COut>(0))::value>::type
addAll(CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::inserter(to, to.begin())); }
如果可以使用 C++14 或更高版本,则还可以定义具有以下值的模板变量
template <typename T>
constexpr bool hasPushBack_v = decltype(hasPushBack<T>(0))::value;
您可以按如下方式简化功能
template<typename CIn, typename COut>
std::enable_if_t<true == hasPushBack_v<COut>>
addAll (CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::back_inserter(to)); }
template<typename CIn, typename COut>
std::enable_if_t<false == hasPushBack_v<COut>>
addAll(CIn && from, COut && to)
{ std::copy(std::begin(from), std::end(from), std::inserter(to, to.begin())); }
只是为了好玩,从 C++14 开始你也可以使用变量模板
template <class...> using void_t = void; // (compensate C++14 lack)
template <class T, class = void>
constexpr bool HasPushBack{false};
template <class T>
constexpr bool HasPushBack<T, void_t<
decltype(std::declval<T>().push_back(std::declval<typename std::decay_t<T>::value_type>()))>
>{true};
template<typename CIn, typename COut, std::enable_if_t< HasPushBack<COut>,bool> = true>
void addAll(CIn && from, COut && to) {
std::copy(std::begin(from), std::end(from), std::back_inserter(to));
}
template<typename CIn, typename COut, std::enable_if_t<!HasPushBack<COut>,bool> = true>
void addAll(CIn && from, COut && to) {
std::copy(std::begin(from), std::end(from), std::inserter(to, to.begin()));
}
<</div>
div class="answers"> 您可以在 std::enable_if
和 std::void_t
的帮助下应用 SFINAE
template <typename T, typename = void>
struct has_push_back : std::false_type {};
template <typename T>
struct has_push_back<T, std::void_t<decltype(std::declval<T>().push_back(std::declval<typename T::value_type>()))>>
: std::true_type {};
// IF HAS_PUSH_BACK:
template<typename CIn, typename COut>
std::enable_if_t<has_push_back<std::remove_reference_t<COut>>::value> addAll(CIn && from, COut && to) {
std::copy(std::begin(from), std::end(from), std::back_inserter(to));
}
// IF ! HAS_PUSH_BACK:
template<typename CIn, typename COut>
std::enable_if_t<!has_push_back<std::remove_reference_t<COut>>::value> addAll(CIn && from, COut && to) {
std::copy(std::begin(from), std::end(from), std::inserter(to, to.begin()));
}
住
相关文章:
- 推导 std::vector::back() 的返回类型
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- vector.push_back(vector.back()+1) 是未定义的行为吗?
- 线路抑制状态错误 C4703 可能未初始化的局部指针变量"back"已使用
- std::vector using back(), pop_back(), push_back(), 得到'double free or corruption'错误
- C++ STL-Inserter
- vector.back()和vector.end()有什么区别
- 列表大小为 1,但 front() 和 back() 不相等
- 返回C++中没有 back() 方法的容器的最后一个元素?
- 在非空 std::list 上使用 std::list.back<int>() 时"Segmentation Fault"
- 我们可以使用Back() - 值索引在其上执行向量插入
- 当我运行以下代码添加str.front() str.back时,它给了我200个,但为什么
- 链表回推操作中需要'back pointer'
- 为什么 std::string 的 back() 应该返回对字符的引用?
- VC++ 自动说明符假定矢量的引用限定符<bool>::back的引用限定符
- C: strtok value gives back null
- vector.back() 可以用来为向量的最后一个元素赋值吗?
- 在std::vector中实现back()
- 在push_front属性上有点混淆.intlist.push_front(2 * intlist.back())会做些
- 将对象转换为 char,然后"uncasting it back"